Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //////////////////////////////////////////
- // Main script for Nova's Rad Adventure //
- // by NovaSquirrel 2013 //
- //////////////////////////////////////////
- Gravity <- 0x0020;
- SpriteList <- []; SpriteList.resize(80, null);
- Retraces <- 0;
- local KeyDown = 0, KeyLast = 0, KeyNew = 0, KeyRelease = 0;
- local CameraX = 0;
- const SCREEN_WIDTH = 320
- const SCREEN_HEIGHT = 240;
- local MinCameraX = 0, MaxCameraX = 5000;
- local PlayerIndex = null, PlayerObj = null;
- // define enums /////////////////////////////////
- enum Sounds {
- Jump,
- Toss,
- Die,
- Defeat,
- Hit,
- Get,
- Land,
- Swallow,
- };
- enum Surfaces {
- Screen,
- Overlay,
- Player,
- CommonFG,
- ThemeFG,
- Enemy,
- Effects,
- };
- enum SpriteClass {
- None,
- Player, // special
- Projectile, // hurts people
- Enemy, // hurts player but can be stunned
- };
- enum BlockFlags {
- SolidMiddle = 1
- SolidTop = 2
- SolidBottom = 4
- SlopeL = 8
- SlopeR = 16
- DrawOutline = 32
- CommonSheet = 64
- FallThrough = 128
- };
- enum KeyMask {
- Left = 1
- Right = 2
- Up = 4
- Down = 8
- A = 16
- B = 32
- X = 64
- Y = 128
- SL = 256
- SR = 512
- };
- // define base classes //////////////////////////
- class Sprite {
- // flags and info
- Edible = false
- static Class = SpriteClass.None
- CanPickup = false
- IsCarried = false
- MaxDistanceRun = 0
- // location and speed
- PosX = 0
- PosY = 0
- VelX = 0
- VelY = 0
- HFlip = false
- // for collisions
- Width = 0
- Height = 0
- StandingOnSolid = false
- OldStandingOnSolid = false
- SideBlocked = false
- WillFallThrough = false
- function Run() {}
- function Draw() {}
- function CanPickupEffect() {
- api.SpriteBlit(Surfaces.Effects, (rand()&1)<<3, 0, (PosX>>8)+Width/2+(sin(Retraces/2.0)*Width/2)-4, (PosY>>8)+Height/2+(cos(Retraces/2.0)*Height/2)-4, 8, 8);
- }
- function ApplyVelocity(VelocityX, VelocityY) {
- OldStandingOnSolid = StandingOnSolid;
- StandingOnSolid = false;
- SideBlocked = false;
- local OldPosX = PosX, OldPosY = PosY;
- // check against touching stuff
- if(VelocityX > 0) {
- if(!lib.ChkBlockFlagXY(((PosX+VelocityX)>>8)+Width-1, (PosY>>8) + (Height/2), BlockFlags.SolidMiddle)
- && !lib.ChkBlockFlagXY(((PosX+VelocityX)>>8)+Width-1, (PosY>>8) + (Height-1), BlockFlags.SolidMiddle)
- && !lib.ChkBlockFlagXY(((PosX+VelocityX)>>8)+Width-1, (PosY>>8), BlockFlags.SolidMiddle))
- PosX += VelocityX;
- else {
- PosX = (((PosX+VelocityX)+(Width-1<<8)) & ~0xfff) - (16<<8);
- SideBlocked = true;
- }
- } else {
- if(!lib.ChkBlockFlagXY((PosX+VelocityX)>>8, (PosY>>8) + (Height/2), BlockFlags.SolidMiddle)
- && !lib.ChkBlockFlagXY((PosX+VelocityX)>>8, (PosY>>8) + (Height-1), BlockFlags.SolidMiddle)
- && !lib.ChkBlockFlagXY((PosX+VelocityX)>>8, (PosY>>8), BlockFlags.SolidMiddle))
- PosX += VelocityX;
- else {
- PosX = ((PosX-VelocityX) & ~0xfff);
- SideBlocked = true;
- }
- }
- PosY += VelocityY;
- // check for flat floor (best kind)
- if(lib.ChkBlockFlagXY((PosX>>8), (PosY>>8) + Height, BlockFlags.SolidTop)
- || lib.ChkBlockFlagXY((PosX>>8)+(Width-1), (PosY>>8) + Height, BlockFlags.SolidTop)) {
- local CanFallLeft = lib.ChkBlockFlagXY((PosX>>8), (PosY>>8) + Height, BlockFlags.FallThrough);
- local CanFallRight = lib.ChkBlockFlagXY((PosX>>8) + Width - 1, (PosY>>8) + Height, BlockFlags.FallThrough);
- if((VelocityY >= 0 && ((((PosY>>8) + Height) >>4) != (((OldPosY>>8) + Height - 1)>>4)))
- && !(WillFallThrough && CanFallLeft && CanFallRight)) {
- PosY = ((PosY+(Height<<8)) & 0xf000)-(Height<<8);
- VelY = 0;
- StandingOnSolid = true;
- }
- }
- // slopes mostly fixed but still a bit buggy
- if(lib.ChkBlockFlagXY((PosX>>8)+(Width-1), (PosY>>8)+Height-1, BlockFlags.SlopeL) && VelocityY >= 0) {
- local PartX = ((PosX>>8)+(Width-1))&15, PartY = ((PosY>>8)+(Height-1))&15, MaxY = 15-PartX;
- if(PartY>MaxY) PosY = (((((PosY>>8)+Height-1) & ~15)) - Height + MaxY) <<8;
- StandingOnSolid = true;
- }
- if(lib.ChkBlockFlagXY((PosX>>8), (PosY>>8)+Height-1, BlockFlags.SlopeR) && VelocityY >= 0) {
- local PartX = (PosX>>8)&15, PartY = ((PosY>>8)+(Height-1))&15, MaxY = PartX;
- if(PartY>MaxY) PosY = (((((PosY>>8)+Height-1) & ~15)) - Height + MaxY) <<8;
- StandingOnSolid = true;
- }
- // check for solids above
- if(lib.ChkBlockFlagXY((PosX>>8), (PosY>>8), BlockFlags.SolidMiddle)
- || lib.ChkBlockFlagXY((PosX>>8)+(Width-1), (PosY>>8), BlockFlags.SolidMiddle)) {
- VelY = 0x0f0;
- }
- if(lib.ChkBlockType((PosX>>8), (PosY>>8) + Height - 1, 23)
- || lib.ChkBlockType((PosX>>8)+(Width-1), (PosY>>8) + Height - 1, 23)) {
- VelY = -0x0500;
- }
- }
- };
- class EnemySprite extends Sprite {
- Class = SpriteClass.Enemy
- StunTime = 0
- function ChkBouncedOn() {
- if(lib.SpriteTouching(this,SpriteList[PlayerIndex])) {
- if(((this.PosY>>8)+this.Height/2) > (SpriteList[PlayerIndex].PosY>>8)+(SpriteList[PlayerIndex].Height)) {
- api.PlaySound(Sounds.Hit);
- SpriteList[PlayerIndex].VelY = -0x200;
- StunTime = 200;
- CanPickup = true;
- }
- }
- }
- function NotCarried() {
- CanPickup = false;
- IsCarried = false;
- if(this == PlayerObj.CarriedObject) {
- PlayerObj.CarriedObject = null;
- PlayerObj.IsCarryingStuff = false;
- }
- }
- };
- class GoombaEnemy extends EnemySprite {
- Width = 16
- Height = 16
- MaxDistanceRun = 500
- function Run() {
- VelY += Gravity;
- ChkBouncedOn();
- if(SideBlocked)
- HFlip = !HFlip;
- if(StunTime) {
- VelX = 0;
- StunTime--;
- } else {
- NotCarried();
- if(StandingOnSolid) {
- VelX = -0x140;
- if(HFlip)
- VelX *= -1;
- }
- }
- ApplyVelocity(VelX,VelY);
- }
- function Draw() {
- api.SpriteBlit(Surfaces.Enemy, 0, 16, PosX>>8, PosY>>8, 16, 16, (Retraces&8)!=0);
- if(StunTime)
- CanPickupEffect();
- }
- }
- class PlayerSprite extends Sprite {
- Class = SpriteClass.Player
- Width = 16
- Height = 24
- WalkAnimTimer = 0
- HFlip = true
- IsCarryingStuff = false
- CarriedObject = null
- HeadFrame = 0
- SwallowTimer = 0;
- CanMove = true;
- FatTimer = 0;
- HoldingDownTimer = 0;
- function Swallow() {
- if(FatTimer) return;
- lib.DeleteSprite(CarriedObject);
- CarriedObject = null;
- IsCarryingStuff = false;
- SwallowTimer = 1;
- CanMove = false;
- api.PlaySound(Sounds.Swallow);
- }
- function AdjustCamera() {
- local ScreenX = (PosX>>8) - CameraX + (Width/2);
- local LeftEdge = (SCREEN_WIDTH/8)*3;
- local RightEdge = (SCREEN_WIDTH/8)*5;
- if(ScreenX < LeftEdge) CameraX -= LeftEdge - ScreenX;
- if(ScreenX > RightEdge) CameraX += ScreenX - RightEdge;
- if(CameraX < MinCameraX) CameraX = MinCameraX;
- if(CameraX > MaxCameraX) CameraX = MaxCameraX;
- }
- function Run() {
- VelX = 0;
- VelY += Gravity;
- if(FatTimer) VelY += 0x0010;
- HeadFrame = 0;
- if(!(KeyDown & KeyMask.Down))
- HoldingDownTimer = 0;
- else
- HoldingDownTimer++;
- WillFallThrough = (HoldingDownTimer > 10);
- if(FatTimer)
- FatTimer--;
- if(SwallowTimer) {
- SwallowTimer++;
- if(SwallowTimer < 10) {
- HeadFrame = 3;
- } else if (SwallowTimer < 20) {
- HeadFrame = 4;
- } else if (SwallowTimer == 20) {
- CanMove = true;
- FatTimer = 200;
- }
- }
- if(CanMove) {
- if(KeyDown & KeyMask.Left) {
- HFlip = false
- VelX = -0x0180;
- WalkAnimTimer++;
- if(KeyDown & KeyMask.Y) {
- VelX *= 2;
- WalkAnimTimer++;
- }
- }
- if(KeyDown & KeyMask.Right) {
- HFlip = true
- VelX = 0x0180;
- WalkAnimTimer++;
- if(KeyDown & KeyMask.Y) {
- VelX *= 2;
- WalkAnimTimer++;
- }
- }
- if(KeyDown & KeyMask.Y && !IsCarryingStuff) {
- local i;
- foreach(i in SpriteList)
- if(i != null && i.CanPickup && !i.IsCarried && lib.SpriteDistance(this,i)<30) {
- api.PlaySound(Sounds.Get);
- i.IsCarried = true;
- IsCarryingStuff = true;
- CarriedObject = i;
- break;
- }
- }
- if(KeyNew & KeyMask.B && StandingOnSolid) {
- VelY = -0x0380;
- api.PlaySound(Sounds.Jump);
- }
- if(KeyNew & KeyMask.A && StandingOnSolid)
- VelY = -0x0500;
- if(IsCarryingStuff && KeyDown & KeyMask.Down)
- HeadFrame = 2;
- }
- if(!VelX)
- WalkAnimTimer = 0
- if(WalkAnimTimer>=13)
- WalkAnimTimer = 1;
- ApplyVelocity(VelX, VelY);
- AdjustCamera();
- }
- function Draw() {
- // tail
- api.SpriteBlit(Surfaces.Player, 32, 0, (PosX>>8)+(HFlip?-4:12), (PosY>>8)+6, 8, 16, HFlip);
- // torso+head
- api.SpriteBlit(Surfaces.Player, 0, HeadFrame<<4, PosX>>8, PosY>>8, 16, 16, HFlip);
- // legs
- local LegsFrame = 0;
- if(WalkAnimTimer) LegsFrame = (WalkAnimTimer&&(WalkAnimTimer<=6))?1:0;
- if(!StandingOnSolid) LegsFrame = 1;
- if(FatTimer) LegsFrame += 2;
- if(FatTimer && FatTimer < 50 && Retraces&16) LegsFrame -= 2;
- api.SpriteBlit(Surfaces.Player, 16, LegsFrame<<3, PosX>>8, (PosY>>8)+16, 16, 8, HFlip);
- }
- }
- class ActiveBlock {
- constructor(SetFlags, OnTouch) {
- Flags = SetFlags;
- SpriteTouch = OnTouch;
- }
- Flags = 0;
- SpriteTouch = null; // (Sprite, LevelX, LevelY, CheckType)
- }
- BlockData <- {
- [0] = ActiveBlock(BlockFlags.FallThrough, null),
- [1] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.SolidMiddle|BlockFlags.SolidBottom, null),
- [2] = ActiveBlock(BlockFlags.SolidBottom|BlockFlags.SlopeL, null),
- [3] = ActiveBlock(BlockFlags.SolidBottom|BlockFlags.SlopeR, null),
- [7] = ActiveBlock(BlockFlags.SlopeL|BlockFlags.FallThrough, null),
- [8] = ActiveBlock(BlockFlags.SlopeR|BlockFlags.FallThrough, null),
- [11] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.FallThrough, null),
- [17] = ActiveBlock(BlockFlags.SolidTop, null),
- [14] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.SolidMiddle, null), // spikes
- [15] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.SolidMiddle, null), // spikes
- [18] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.SolidMiddle, null), // box
- [19] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.SolidMiddle, null), // checker box
- [20] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.SolidMiddle, null), // checker box
- [21] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.SolidMiddle, null), // checker box
- [22] = ActiveBlock(BlockFlags.SolidTop|BlockFlags.SolidMiddle, null), // checker box
- [23] = ActiveBlock(0, null), // springboard
- [24] = ActiveBlock(0, null), // floor switch
- };
- // define helper functions //////////////////////
- lib <- {
- function DeleteSprite(Obj) {
- for(local i=0;i<SpriteList.len();i++)
- if(SpriteList[i] == Obj) {
- SpriteList[i] = null;
- return;
- }
- }
- function AllocSprite() {
- return SpriteList.find(null);
- }
- function ChkBlockFlagId(t) {
- return (t in BlockData && BlockData[t].Flags&Mask)?true:false;
- }
- function ChkBlockFlagXY(X, Y, Mask) {
- local t = api.GetBlock(X>>4,Y>>4);
- return (t in BlockData && BlockData[t].Flags&Mask)?true:false;
- }
- function ChkBlockType(X, Y, Type) {
- local t = api.GetBlock(X>>4,Y>>4);
- return t == Type;
- }
- function SpriteDistance(Obj1, Obj2) {
- local X1 = (Obj1.PosX>>8)+Obj1.Width/2;
- local Y1 = (Obj1.PosY>>8)+Obj1.Height/2;
- local X2 = (Obj2.PosX>>8)+Obj2.Width/2;
- local Y2 = (Obj2.PosY>>8)+Obj2.Height/2;
- return sqrt(pow((X2-X1),2)+pow((Y2-Y1),2)).tointeger();
- }
- function SpriteTouching(Obj1, Obj2) {
- local LeftA, RightA, TopA, BottomA;
- local LeftB, RightB, TopB, BottomB;
- LeftA = Obj1.PosX>>8;
- RightA = LeftA+Obj1.Width-1;
- TopA = Obj1.PosY>>8;
- BottomA = TopA+Obj1.Height-1;
- if(typeof(Obj2)!="array") {
- LeftB = Obj2.PosX>>8;
- RightB = LeftB+Obj2.Width-1;
- TopB = Obj2.PosY>>8;
- BottomB = TopB+Obj2.Height-1;
- } else {
- LeftB = Obj2[0];
- RightB = LeftB+Obj2[1]-1;
- TopB = Obj2[1];
- BottomB = TopB+Obj[3]-1;
- }
- if(BottomA <= TopB) return false;
- if(TopA >= BottomB) return false;
- if(RightA <= LeftB) return false;
- if(LeftA >= RightB) return false;
- return true;
- }
- };
- event <- {
- function UpdateKeys(Down, Last, New) {
- KeyDown = Down;
- KeyLast = Last;
- KeyNew = New;
- KeyRelease = ~KeyDown & KeyLast;
- }
- };
- // init stuff ///////////////////////////////////
- PlayerIndex = lib.AllocSprite();
- SpriteList[PlayerIndex] = PlayerSprite();
- SpriteList[PlayerIndex].PosX = 16<<8;
- PlayerObj = SpriteList[PlayerIndex];
- // test stuff //////
- event.GameLoop <- function() {
- local i;
- Retraces++;
- foreach(i in SpriteList)
- if(i != null) {
- if(i.MaxDistanceRun && lib.SpriteDistance(i, PlayerObj) > i.MaxDistanceRun)
- continue;
- i.Run();
- if(i.IsCarried) {
- if(KeyDown & KeyMask.Down && KeyRelease & KeyMask.Y && PlayerObj.StandingOnSolid == true) {
- PlayerObj.Swallow();
- } else {
- i.PosX = PlayerObj.PosX + (PlayerObj.HFlip?0x800:-0x800);
- if(PlayerObj.HeadFrame == 2)
- i.PosX = PlayerObj.PosX + (PlayerObj.HFlip?0x500:-0x500);
- if(i.Class = SpriteClass.Enemy && i.StunTime < 50)
- i.PosX += Retraces&1?0x100:-0x100;
- i.PosY = PlayerObj.PosY + 0x400;
- if(KeyRelease & KeyMask.Y) {
- PlayerObj.IsCarryingStuff = false;
- PlayerObj.CarriedObject = null;
- i.IsCarried = false;
- if(i.Class = SpriteClass.Enemy)
- i.StunTime = 0;
- i.HFlip = PlayerObj.HFlip;
- i.VelX = PlayerObj.HFlip?0x100:-0x100;
- i.VelY = -0x200;
- if(KeyDown & KeyMask.Up) {
- i.VelX /= 2;
- i.VelY = -0x400;
- }
- if(KeyDown & KeyMask.Down && PlayerObj.StandingOnSolid == false) {
- i.VelX *= 2;
- i.VelY = 0x400;
- PlayerObj.VelY = -0x300;
- }
- }
- }
- }
- }
- api.SetCamera(CameraX, 0);
- foreach(i in SpriteList)
- if(i != null)
- i.Draw();
- }
- local LevelEntrances = {};
- event.AddPoint <- function(PosX, PosY, Type, Meta) {
- local S = lib.AllocSprite();
- function AddSprite(SpriteType) {
- local S = lib.AllocSprite();
- if(S == null) return;
- SpriteList[S] = SpriteType;
- SpriteList[S].PosX = PosX << 12;
- SpriteList[S].PosY = PosY << 12;
- }
- // print("Adding " + PosX + "," + PosY + " - " + Type)
- switch(Type) {
- case 0x0100: AddSprite(GoombaEnemy()); break;
- case 0x0102: LevelEntrances[Meta] <- [PosX,PosY]; break;
- }
- }
- if(0 in LevelEntrances) {
- PlayerObj.PosX = LevelEntrances[0][0]<<12;
- PlayerObj.PosY = LevelEntrances[0][1]<<12;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement