Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
2323 lines (2116 sloc) 86.7 KB
import { InputController } from "./input_controller";
import { FPSController } from "./fps_controller";
export enum GameType{
MARIO = 0,
GOOMBA = 1,
COINBLOCK = 2,
MUSHROOM = 3,
COIN = 4,
PLATFORM = 5,
LAVA = 6,
FIREBALL = 7,
FIRERING = 8,
BOWSER = 9,
BOWSERFIRE = 10,
TURTLE = 11
}
export enum GameState{
GAME_STATE_LOADING = 0,
GAME_STATE_INTRO = 1,
GAME_STATE_PLAYING = 2,
GAME_STATE_PAUSED = 3,
GAME_STATE_WON = 4,
}
export class Animator
{
x:number;
y:number;
curr_frame:number;
width:number;
height:number;
frames:HTMLImageElement[] = [];
constructor(x:number,y:number,width:number,height:number)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
LoadFrame(filename:string)
{
let frame = new Image();
frame.src = filename;
this.frames.push(frame);
}
}
export class SpecialObject
{
type = 0; //what is it
x=0; y=0; //coordinates
height=0; width=0; //dimensions
alive:boolean; //does it exist in the system
marioTransparent:boolean; //for collision detection
objectTransparent:boolean;
animator:number; //animation counter
currFrame:number; //current frame of animation
ySpeed:number; //speed of vertical motion
velocity:number; //speed of object
state:number;
image:HTMLImageElement;
};
export class MarioGame{
// GLOBALS ////////////////////////////////////////////////
/*
**********GRID CHART**********
*
0-BLANK SPACE
1-BREAKABLE BROWN BLOCK
2,3-PIPE MIDSECTION
4,5-PIPE TOP
8-UNBREAKABLE BROWN BLOCK
a-GOOMBA
b-COIN BLOCK
c-MUSHROOM BLOCK
d-COIN
e-FALLING PLATFORM
f-SIDE TO SIDE PLATFORM
g-UP DOWN PLATFORM
--BOWSER'S CASTLE--
6-UNBREAKABLE GRAY BRICK BLOCK
7-UNBREAKABLE REGULAR BLOCK
h-LAVA
i-LAVA WITH RISING FIREBALL
j-SPINNING FIRE RING
k-BOWSER
*/
screenWidth:number = 0;
screenHeight:number = 0;
ctx:CanvasRenderingContext2D;
sampleImage = new Image();
sampleX = 100;
sampleY = 100;
inputController:InputController;
isMobile:boolean = false;
//world
gravity = 2; //gravity on objects
velocity = 0; //how fast mario is going
marioX = 70; //mario's top left corner
marioY = 350; //mario's top left corner
animationCounter = 0; //counts which frame mario is on
backSprites = 9; //number of sprites used for level
direction = 0; //0==right 1==left
maxVelocity = 7; //max speed of mario walking
acceleration = .5; //mario's acceleration
width = 40; height = 40; //mario's bounding box
worldHeight = 12; worldWidth = 128; //world's grid dimensions
slideFriction = 1; //how much mario slides
flying = 0; //if mario is in the air 0==false 1==true
jumpCounter = 0; //counts how many frames mario has been jumping for
jumpLimit = 8; //how many frames mario can jump for
jumpAcceleration = 0; //mario's maximum vertical acceleration (set to jumpSpeed)
ySpeed = 0; //speed mario is rising or falling
jumpReset = 0; //ready for jumping 0=true 1=false
jumpSpeed = 15; //speed constant for jumping
jumpSpeedRunning = 4;//mario can jump a little higher
camera = 0; //camera's x coordinate
// specialSize = 0; //current size of special characters
goombaVelocity = -1; //goomba's speed
mushroomVelocity = 2; //mushroom's speed
killCount = 0; //number of times mario has died
coinAnimator = 0; //coin animator
lavaAnimator = 0; //coin animator
lives = 1000; //don't limit lives
coins = 0;
currentLevel = 0;
gameOver:boolean = false;
gameOverCounter = 0;
bigHeight = 60;
numLevels = 8;
gameState = 0;
dying:boolean = false;
dyingCounter = 0;
dyingX = 0;
dyingY = 0;
winningCounter = 0;
specialCharacters:SpecialObject[];
marioObject:SpecialObject = new SpecialObject();
grid:string[][] = [];
tempgrid:string[][] = [];
level1:string[][] = [];
level2:string[][] = [];
level3:string[][] = [];
level4:string[][] = [];
level5:string[][] = [];
level6:string[][] = [];
level7:string[][] = [];
level8:string[][] = [];
backColor:number = 0;
startinglivesnum = 10;
hardwareaccelerate = true;
platformVelocity = 4;
platformTurnaroundFrames = 60;
winScreen = new Image();
mario:Animator;
bigMario:Animator;
tiles:Animator;
goomba:Animator;
coinBlock:Animator;
gameOverScreen:Animator;
mushroom:Animator;
coin:Animator;
platform:Animator;
lava:Animator;
fireball:Animator;
firering:Animator;
bowser:Animator;
bowserfire:Animator;
turtle:Animator;
runkey = false;
jumpkey = false;
leftkey = false;
rightkey = false;
isSixtyFPSmode = false;
firstTimeFpsCheck:boolean = true;
constructor(screenWidth:number,screenHeight:number,ctx:CanvasRenderingContext2D,inputController:InputController,
isMobile:boolean,isSixtyFPSmode:boolean){
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.ctx = ctx;
this.sampleImage.src = "Images/mario1.png";
this.inputController = inputController;
this.isMobile = isMobile;
//adjust physics from 30FPS to 60FPS
this.isSixtyFPSmode = isSixtyFPSmode;
if (isSixtyFPSmode)
{
this.gravity = 1;
this.maxVelocity = 4.0;
this.acceleration = .25;
this.slideFriction = .5;
this.jumpLimit = 17;
this.jumpSpeed = 8;
this.jumpSpeedRunning = 2.5;
this.goombaVelocity = -.5;
this.mushroomVelocity = 1;
this.platformVelocity = 2;
this.platformTurnaroundFrames = 120;
}
//ported code
this.initgame();
}
clearScreen(){
let gradient_mode = true;
if (gradient_mode)
{
var my_gradient = this.ctx.createLinearGradient(0, 0, 0, 480);
if (this.currentLevel != 4 && this.currentLevel != 8)
{
my_gradient.addColorStop(0, "#D1E4EA");
my_gradient.addColorStop(1, "lightblue");
}
else
{
my_gradient.addColorStop(0, "#F0EAE6");
my_gradient.addColorStop(1, "#efbf99");
}
this.ctx.fillStyle = my_gradient;
}
else
{
let backcolor = "lightblue";
if (this.currentLevel == 4 || this.currentLevel == 8)
{
backcolor = "#f0eae6";
}
this.ctx.fillStyle = backcolor;
}
this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
}
draw(){
this.clearScreen();
this.updateInput();
this.countFPS();
if (this.gameState == GameState.GAME_STATE_LOADING)
{
this.loading_screen()
}
if (this.gameState == GameState.GAME_STATE_INTRO)
{
//TODO draw intro screen
}
if (this.gameState == GameState.GAME_STATE_PLAYING)
{
this.gameMain();
this.drawSTATS();
}
if (this.gameState == GameState.GAME_STATE_PAUSED)
{
}
if (this.gameState == GameState.GAME_STATE_WON)
{
this.win();
}
}
lastCalledTime = new Date();
fpscounter = 0;
currentfps = 0;
countFPS(){
this.fpscounter++;
let delta = (new Date().getTime() - this.lastCalledTime.getTime())/1000;
if (delta>1)
{
this.currentfps = this.fpscounter;
this.fpscounter = 0;
this.lastCalledTime = new Date();
}
}
drawSTATS()
{
this.ctx.font = "bold 18px Comic Sans MS";
this.ctx.fillStyle = "#F3F0F0";
this.ctx.fillRect(52,5,185,28);
this.ctx.fillStyle = "#FF0000";
this.ctx.fillText("Level: " + this.currentLevel.toString(), 60, 25);
this.ctx.fillText("FPS: " + this.currentfps.toString(), 160, 25);
}
updateInput(){
this.inputController.update();
if (this.inputController.Key_Action_1==false)
this.runkey = false;
if (this.inputController.Key_Action_2==false)
this.jumpkey = false;
if (this.inputController.Key_Left==false)
this.leftkey = false;
if (this.inputController.Key_Right==false)
this.rightkey = false;
if (this.inputController.Key_Action_1==true)
this.runkey = true;
if (this.inputController.Key_Action_2==true)
this.jumpkey = true;
if (this.inputController.Key_Left==true)
this.leftkey = true;
if (this.inputController.Key_Right==true)
this.rightkey = true;
}
initgame()
{
this.specialCharacters = [];
this.grid = [];
for (let i = 0; i < 12; i++)
{
let arr1:string[] = [];
this.grid.push(arr1);
}
this.tempgrid = [];
this.loadbitmaps();
this.startGame();
}
//so that i can debug the loading sequence
async startGame(){
await this.loadLevel(1);
}
loadbitmaps(){
this.tiles = new Animator(0, 0, 40, 40);
for (let index = 0; index < this.backSprites; index++)
{
this.tiles.LoadFrame("Images/background" + index + ".png");
}
this.mario = new Animator(0, 0, 40, 40);
for (let index = 1; index < 10; index++)
{
this.mario.LoadFrame("Images/mario" + index + ".png");
}
this.bigMario = new Animator(0, 0, 40, 60);
for (let index = 0; index < 8; index++)
{
this.bigMario.LoadFrame("Images/b" + index + ".png");
}
this.goomba = new Animator(0, 0, 40, 40);
for (let index = 0; index < 3; index++)
{
this.goomba.LoadFrame("Images/goomba" + index + ".png");
}
this.coinBlock = new Animator(0, 0, 40, 40);
for (let index = 0; index < 4; index++)
{
this.coinBlock.LoadFrame("Images/block" + index + ".png");
}
this.mushroom = new Animator(0, 0, 40, 40);
this.mushroom.LoadFrame("Images/mushroom.png");
this.coin = new Animator(0, 0, 40, 40);
this.coin.LoadFrame("Images/coin.png");
this.platform = new Animator(0, 0, 80, 20);
this.platform.LoadFrame("Images/platform.png");
this.lava = new Animator(0, 0, 40, 40);
for (let index = 0; index < 2; index++)
{
this.lava.LoadFrame("Images/lava" + index + ".png");
}
this.fireball = new Animator(0, 0, 40, 40);
for (let index = 0; index < 2; index++)
{
this.fireball.LoadFrame("Images/fire" + index + ".png");
}
this.firering = new Animator(0, 0, 20, 20);
for (let index = 0; index < 4; index++)
{
this.firering.LoadFrame("Images/smallfire" + index + ".png");
}
this.bowser = new Animator(0, 0, 80, 80);
for (let index = 0; index < 2; index++)
{
this.bowser.LoadFrame("Images/bowser" + index + ".png");
}
this.bowserfire = new Animator(0, 0, 40, 20);
for (let index = 0; index < 2; index++)
{
this.bowserfire.LoadFrame("Images/bowserfire" + index + ".png");
}
this.turtle = new Animator(0, 0, 40, 40);
for (let index = 1; index < 6; index++)
{
this.turtle.LoadFrame("Images/turtle" + index + ".png");
}
this.winScreen.src = "Images/winscreen.jpg";
}
async loadLevel(level:number)
{
this.gameState = GameState.GAME_STATE_LOADING;
await this.loadFile(level);
this.resetLevel();
this.currentLevel = level;
this.log();
this.gameState = GameState.GAME_STATE_PLAYING;
}
resetLevel()
{
for (let i = 0; i < 12; i++)
{
this.grid[i] = [];
}
for (let i = 0; i < 12; i++)
{
for (let j = 0; j < this.tempgrid[i].length; j++)
{
this.grid[i].push(this.tempgrid[i][j]);
}
}
this.worldHeight = 12; //worldWidth = 128; //world's grid dimensions
this.marioX = 70; //mario's top left corner
this.marioY = 350; //mario's top left corner
this.backColor = 287;
this.dying = false;
this.gameOver = false;
this.gameOverCounter = 0;
this.animationCounter = 0; //counts which frame mario is on
this.direction = 0; //0==right 1==left
this.flying = 0; //if mario is in the air 0==false 1==true
this.jumpCounter = 0; //counts how many frames mario has been jumping for
this.ySpeed = 0; //speed mario is rising or falling
this.velocity = 0;
this.jumpReset = 0; //ready for jumping 0=true 1=false
this.specialCharacters = [];
this.camera = 0; //camera's x coordinate
this.coinAnimator = 0; //coin animator
this.lavaAnimator = 0; //coin animator
this.killCount = 0; //number of times mario has died
this.mario.curr_frame = 0;
this.mario.x = this.marioX;
this.mario.y = this.marioY;
this.marioObject.type = GameType.MARIO;
this.marioObject.x = this.marioX;
this.marioObject.y = this.marioY;
this.marioObject.height = this.height;
this.marioObject.width = this.width;
this.marioObject.image = null;
}
async loadFile(level:number)
{
let filename = 'Levels/level' + level + '.txt';
let leveltext = await $.get(filename) as string;
console.log(filename + ' - LOADED');
this.tempgrid = [];
let level_rows = leveltext.split("\r\n");
for (let i = 0; i < 12; i++)
{
let line = level_rows[i];
let arr1:string[] =[];
for (let j = 0; j < line.length; j++)
arr1.push(line.charAt(j));
this.tempgrid.push(arr1);
this.worldWidth = line.length;
}
}
async log(){
//add a slight delay to allow animation loop to settle
await new Promise<void>(resolve => { setTimeout(resolve, 2000); });
//do we need to enable frame skipping?
if (this.firstTimeFpsCheck)
{
this.determineIfFrameSkippingEnabled();
}
if (document.location.href.toLocaleLowerCase().indexOf('neilb.net')>1)
{
let referrer = document.referrer;
if(referrer==null || referrer=="")
referrer = "NONE";
$.get('https://neilb.net/tetrisjsbackend/api/stuff/addmarioscore?level=' + this.currentLevel + '&lives=' + this.lives + '&fps=' + this.currentfps + '&referrer=' + referrer);
}
}
//fix for high refresh monitors making the game run too fast
//only determine this when the game first loads to avoid
//random dips and spikes from triggering frame skipping
async determineIfFrameSkippingEnabled(){
if(this.isSixtyFPSmode==true)
{
if (this.currentfps>70)
{
let fpsController = window["myApp"].fpsController as FPSController;
fpsController.UpdateTargetFPS(60);
fpsController.enabled = true;
console.log('frame skipping enabled');
}
}
//TODO move this functionality into the FPS Controller class
this.firstTimeFpsCheck = false;
}
gameMain(){
//BACKGROUND ANIMATORS
this.animate_bg_objects();
//MOVE MARIO
if (!this.gameOver && !this.dying)
{
this.MARIO_RUN_PHYSICS(); //process mario's jumping and velocity
this.MARIO_MOVE_X(); //adjust mario's horizontal motion
this.MARIO_MOVE_Y(); //adjust mario's vertical motion
}
//run scripts for all objects
for (let i = 0; i < this.specialCharacters.length; i++)
{
this.process_object(this.specialCharacters[i], i);
}
this.DRAW_WORLD(); //draws the background
//draws objects
for (let i = 0; i < this.specialCharacters.length; i++)
{
if (this.specialCharacters[i].alive)
this.draw_object(this.specialCharacters[i]);
}
//get lives from coins
if (this.coins > 99)
{
this.coins = 0;
this.lives++;
}
//process dying sequence
if (this.dying)
{
if ((this.dyingCounter % 2) == 1)
{
this.backColor--;
}
else
this.backColor++;
this.mario.curr_frame = 8;
this.mario.x = this.dyingX;
this.mario.y = this.dyingY;
this.Draw_Image(this.mario, this.marioObject);
this.dyingCounter++;
if (this.dyingY > 500)
this.die();
}
if (this.dyingCounter > 30)
{
this.dyingY += 15;
}
//draw_mario
if (!this.gameOver)
{
if (this.height == 40)
{
this.Draw_Image(this.mario, this.marioObject);
}
else
{
this.bigMario.curr_frame = this.mario.curr_frame;
this.bigMario.x = this.mario.x;
this.bigMario.y = this.mario.y;
this.Draw_Image(this.bigMario, this.marioObject);
}
}
//remove objects that are beyond the camera
this.updateList();
//MARIO FELL OFF THE WORLD
if (this.marioY > (this.worldHeight * 2) * 40)
{
this.killMario();
}
//GOTO NEXT LEVEL
if (this.marioX >= (this.worldWidth * 40))
{
if (this.currentLevel < this.numLevels)
{
this.loadLevel(this.currentLevel + 1);
}
else
{
this.mario.x = 50;
this.mario.y = 400;
this.animationCounter = 0;
this.mario.curr_frame = 0;
this.currentLevel++;
this.log();
this.win();
}
}
}
animate_bg_objects(){
this.coinAnimator++;
let coin_anim_change = 46;
if (this.isSixtyFPSmode) coin_anim_change = 91;
if (this.coinAnimator == coin_anim_change)
{
this.coinAnimator = 0;
}
this.lavaAnimator++;
if (this.lavaAnimator == 61)
{
this.lavaAnimator = 0;
}
}
DRAW_WORLD(){
let offset = Math.floor((this.camera / 40));
let gridNum = 0;
for (let i = 0; i < 12; i++)
{
for (let j = offset; j < offset + 17; j++)
{
if (!this.grid[i][j])
continue;
gridNum = this.grid[i][j].charCodeAt(0) - '0'.charCodeAt(0);
if (gridNum < 49)
{
this.tiles.curr_frame = gridNum;
this.tiles.x = j * 40 - Math.floor(this.camera);
this.tiles.y = i * 40;
if (gridNum != 0)
{
this.Draw_World_Image(this.tiles, i, j);
}
}
else
{
if (gridNum == 49)
{
this.create_object(GameType.GOOMBA, j * 40, i * 40, 40, 40, false, false, this.goombaVelocity, 0, 0);
}
if (gridNum == 52)
{
this.create_object(GameType.COIN, j * 40, i * 40, 40, 40, false, true, 1, 0, 0);
}
if (gridNum == 53)
{
this.create_object(GameType.PLATFORM, j * 40, i * 40, 20, 80, false, false, 0, 0, 0);
}
if (gridNum == 54)
{
this.create_object(GameType.PLATFORM, j * 40, i * 40, 20, 80, false, true, this.platformVelocity, 0, 1);
}
if (gridNum == 55)
{
this.create_object(GameType.PLATFORM, j * 40, i * 40, 20, 80, false, true, this.platformVelocity, 0, 2);
}
if (gridNum == 56)
{
this.create_object(GameType.LAVA, j * 40, i * 40, 40, 40, true, true, 0, 0, 0);
}
if (gridNum == 57)
{
this.create_object(GameType.LAVA, j * 40, i * 40, 40, 40, true, true, 0, 0, 0);
this.create_object(GameType.FIREBALL, j * 40, (i + 1) * 40, 40, 40, false, true, -30, 0, 0);
}
if (gridNum == 59)
{
if (this.isSixtyFPSmode)
this.create_object(GameType.BOWSER, j * 40, i * 40, 80, 80, false, true, -2.5, -.75, -30);
else
this.create_object(GameType.BOWSER, j * 40, i * 40, 80, 80, false, true, -5, -1.5, -30);
}
if (gridNum == 60)
{
this.create_object(GameType.TURTLE, j * 40, i * 40, 40, 40, false, false, this.goombaVelocity, 0, 0);
}
this.grid[i][j] = '0';
if (gridNum == 58)
{
this.grid[i][j] = '7';
this.Draw_World_Image(this.tiles, i, j);
this.create_object(GameType.FIRERING, (j * 40) + 10, (i * 40) + 10, 20, 20, false, true, (j * 40) + 10, (i * 40) + 10, 0);
this.create_object(GameType.FIRERING, (j * 40) + 10, (i * 40) + 10 - 20, 20, 20, false, true, (j * 40) + 10, (i * 40) + 10, 1);
this.create_object(GameType.FIRERING, (j * 40) + 10, (i * 40) + 10 - 40, 20, 20, false, true, (j * 40) + 10, (i * 40) + 10, 2);
this.create_object(GameType.FIRERING, (j * 40) + 10, (i * 40) + 10 - 60, 20, 20, false, true, (j * 40) + 10, (i * 40) + 10, 3);
this.create_object(GameType.FIRERING, (j * 40) + 10, (i * 40) + 10 - 80, 20, 20, false, true, (j * 40) + 10, (i * 40) + 10, 4);
}
if (gridNum == 50)
{
this.create_object(GameType.COINBLOCK, j * 40, i * 40, 40, 40, false, false, 0, 0, 0);
this.grid[i][j] = '0';
}
if (gridNum == 51)
{
this.create_object(GameType.COINBLOCK, j * 40, i * 40, 40, 40, false, false, 1, 0, 0);
this.grid[i][j] = '0';
}
this.tiles.curr_frame = gridNum;
this.tiles.x = j * 40 - Math.floor(this.camera);
this.tiles.y = i * 40;
}
}
}
}
Draw_World_Image(tiles:Animator, i:number, j:number)
{
this.ctx.drawImage(tiles.frames[tiles.curr_frame], tiles.x, tiles.y);
}
Draw_Image(anim:Animator, obj:SpecialObject)
{
this.ctx.drawImage(anim.frames[anim.curr_frame], anim.x, anim.y);
}
MARIO_MOVE_Y()
{
this.ySpeed += this.gravity;
if (this.ySpeed > this.jumpAcceleration)
this.ySpeed = this.jumpAcceleration;
this.marioY += this.ySpeed;
this.flying = 1; //mario is always in the air, unless a collision is detected
let xcood; //grid coordinates of mario
let ycood;
xcood = Math.floor((this.marioX + this.width - 1 - ((this.marioX + this.width - 1) % 40)) / 40);
ycood = Math.floor((this.marioY - ((this.marioY) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth &&
(this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
if ((xcood - 1) >= 0 && (this.grid[ycood][xcood - 1].charCodeAt(0) - '0'.charCodeAt(0)) == 0 && (this.marioX % 40) < 15)
{
this.marioX = this.marioX - (this.marioX % 40);
}
else
{
this.marioY = this.marioY - (this.marioY % 40) + 40;
this.ySpeed = 0;
this.jumpReset = 1;
if (this.height == this.bigHeight && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) == 1)
{
this.grid[ycood][xcood] = '0';
}
}
}
xcood = Math.floor((this.marioX - ((this.marioX) % 40)) / 40);
ycood = Math.floor((this.marioY - ((this.marioY) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0
&& xcood < this.worldWidth && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
if ((xcood + 1) < this.worldWidth && (this.grid[ycood][xcood + 1].charCodeAt(0) - '0'.charCodeAt(0)) == 0
&& (this.marioX % 40) > 25)
{
this.marioX = this.marioX - (this.marioX % 40) + 40;
}
else
{
this.marioY = this.marioY - (this.marioY % 40) + 40;
this.ySpeed = 0;
this.jumpReset = 1;
if (this.height == this.bigHeight && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) == 1)
{
this.grid[ycood][xcood] = '0';
}
}
}
xcood = Math.floor((this.marioX + this.width - 1 - ((this.marioX + this.width - 1) % 40)) / 40);
ycood = Math.floor((this.marioY + this.height - 1 - ((this.marioY + this.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0
&& xcood < this.worldWidth && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
this.marioY = (ycood * 40) - this.height;
this.flying = 0;
this.jumpCounter = 0;
this.ySpeed = 0;
}
xcood = Math.floor((this.marioX - ((this.marioX) % 40)) / 40);
ycood = Math.floor((this.marioY + this.height - 1 - ((this.marioY + this.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth &&
(this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
this.marioY = (ycood * 40) - this.height;
this.flying = 0;
this.jumpCounter = 0;
this.ySpeed = 0;
}
this.updateMario();
let collisionTest:number;
for (let i = 0; i < this.specialCharacters.length; i++)
{
collisionTest = 0;
if (this.specialCharacters[i].alive && !this.specialCharacters[i].marioTransparent)
collisionTest = 4 + this.collision_test(this.marioObject, this.specialCharacters[i]);
if (collisionTest > 4)
this.process_collision(this.marioObject, this.specialCharacters[i], collisionTest, i);
}
if (this.flying == 1)
{
if (this.direction == 0)
{
this.mario.curr_frame = 4;
}
if (this.direction == 1)
{
this.mario.curr_frame = 5;
}
}
this.mario.y = Math.floor(this.marioY);
}
MARIO_RUN_PHYSICS(){
let tempVelocity = this.maxVelocity; //tempVelocity is the current maximum velocity
if (this.runkey) //run button
{
tempVelocity = this.maxVelocity * 2; //mario can run at twice maxVelocity
if (this.velocity > this.maxVelocity || this.velocity < -this.maxVelocity) //once mario reaches a certain speed
this.jumpAcceleration = this.jumpSpeed + this.jumpSpeedRunning; //he can jump a little higher
else
this.jumpAcceleration = this.jumpSpeed;
}
else
this.jumpAcceleration = this.jumpSpeed; //if user lets go of control, reset jumpAcceleration
if (this.leftkey || this.rightkey) //move buttons
{
if (this.rightkey)
{
if (this.velocity < tempVelocity) //if the user is slower that max, keep accelerating
this.velocity += this.acceleration;
else
this.velocity -= this.acceleration; //otherwise slow him down to max
this.direction = 0; //sets the direction
}
if (this.leftkey)
{
if (this.velocity > -tempVelocity)
this.velocity -= this.acceleration;
else
this.velocity += this.acceleration;
this.direction = 1;
}
}
else
{
if (this.direction == 0 && this.velocity > 0) //slow the user down
{
this.velocity -= this.acceleration;
if (this.velocity < 0)
this.velocity = 0;
}
if (this.direction == 1 && this.velocity < 0)
{
this.velocity += this.acceleration;
if (this.velocity > 0)
this.velocity = 0;
}
}
if (this.jumpkey) //jump button
{
if (this.jumpCounter < this.jumpLimit && this.jumpReset == 0) //allow user to keep jumping as long as jumpLimit
{ //hasn't been reached
this.ySpeed = -this.jumpAcceleration; //adjust ySpeed
this.jumpCounter++;
}
else
{
this.jumpReset = 1; //if jumpLimit has been reached, jumpReset needs to be reset before jumping again
}
}
else
{
if (this.flying == 1) //if user is flying, don't let user jump
this.jumpCounter = this.jumpLimit;
this.jumpReset = 0;
}
}
MARIO_MOVE_X()
{
this.marioX += this.velocity; //move mario
//Animation Stuff
if (this.flying == 0)
{
if (this.direction == 0)
{
if (this.velocity > 0 && this.animationCounter <= 0)
{
if (this.isSixtyFPSmode)
{
this.animationCounter = 18 - Math.floor(this.velocity*2);
}
else
{
this.animationCounter = 12 - Math.floor(this.velocity);
}
if (this.mario.curr_frame == 0)
{
this.mario.curr_frame = 1;
}
else
{
this.mario.curr_frame = 0;
}
}
if (this.velocity == 0)
{
this.mario.curr_frame = 0;
}
if (this.velocity < 0)
{
this.velocity += this.slideFriction;
this.mario.curr_frame = 6;
}
}
if (this.direction == 1)
{
if (this.velocity < 0 && this.animationCounter <= 0)
{
if (this.isSixtyFPSmode)
{
this.animationCounter = 18 - Math.floor(this.velocity*2);
}
else
{
this.animationCounter = 12 - Math.floor(this.velocity);
}
if (this.mario.curr_frame == 2)
{
this.mario.curr_frame = 3;
}
else
{
this.mario.curr_frame = 2;
}
}
if (this.velocity == 0)
{
this.mario.curr_frame = 2;
}
if (this.velocity > 0)
{
this.velocity -= this.slideFriction;
this.mario.curr_frame = 7;
}
}
this.animationCounter--;
}
let xcood; //grid coordinates of mario
let ycood;
xcood = Math.floor((this.marioX + this.width - 1 - ((this.marioX + this.width - 1) % 40)) / 40);
ycood = Math.floor((this.marioY - ((this.marioY) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 &&
xcood < this.worldWidth && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
this.marioX = (xcood * 40) - this.width;
this.velocity = 0;
}
xcood = Math.floor((this.marioX - ((this.marioX) % 40)) / 40);
ycood = Math.floor((this.marioY - ((this.marioY) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth &&
(this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
this.marioX = this.marioX - (this.marioX % 40) + 40;
this.velocity = 0;
}
xcood = Math.floor((this.marioX + this.width - 1 - ((this.marioX + this.width - 1) % 40)) / 40)
ycood = Math.floor((this.marioY + this.height - 1 - ((this.marioY + this.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth &&
(this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
this.marioX = (xcood * 40) - this.width;
this.velocity = 0;
}
xcood = Math.floor((this.marioX - ((this.marioX) % 40)) / 40);
ycood = Math.floor((this.marioY + this.height - 1 - ((this.marioY + this.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth &&
(this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
this.marioX = this.marioX - (this.marioX % 40) + 40;
this.velocity = 0;
}
this.updateMario();
let collisionTest;
for (let i = 0; i < this.specialCharacters.length; i++)
{
collisionTest = 0;
if (this.specialCharacters[i].alive && !this.specialCharacters[i].marioTransparent)
collisionTest = this.collision_test(this.marioObject, this.specialCharacters[i]);
if (collisionTest > 0)
this.process_collision(this.marioObject, this.specialCharacters[i], collisionTest, i);
}
let camera_front = 240;
if (this.isMobile)
camera_front = 100;
if (this.marioX > this.camera + camera_front)
{
this.camera = this.marioX - camera_front;
if (Math.floor(this.camera / 40) >= (this.worldWidth - 16))
{
this.camera = (this.worldWidth - 16) * 40;
}
}
if (this.marioX < this.camera)
{
this.marioX = this.camera;
this.velocity = 0;
}
this.mario.x = Math.floor(this.marioX) - Math.floor(this.camera);
}
updateMario()
{
this.marioObject.x = this.marioX;
this.marioObject.y = this.marioY;
this.marioObject.height = this.height;
this.marioObject.width = this.width;
}
collision_test(obj:SpecialObject, obj2:SpecialObject)
{
let x:number, y:number;
x = Math.floor(obj.x + obj.width - 1);
y = Math.floor(obj.y);
if (Math.floor(obj2.x) <= x && x <= Math.floor(obj2.x + obj2.width - 1) &&
Math.floor(obj2.y) <= y && y <= Math.floor(obj2.y + obj2.height - 1))
{
return (1);
}
x = Math.floor(obj.x);
y = Math.floor(obj.y);
if (Math.floor(obj2.x) <= x && x <= Math.floor(obj2.x + obj2.width - 1) &&
Math.floor(obj2.y) <= y && y <= Math.floor(obj2.y + obj2.height - 1))
{
return (2);
}
x = Math.floor(obj.x + obj.width - 1);
y = Math.floor(obj.y + obj.height - 1);
if (Math.floor(obj2.x) <= x && x <= Math.floor(obj2.x + obj2.width - 1) &&
Math.floor(obj2.y) <= y && y <= Math.floor(obj2.y + obj2.height - 1))
{
return (3);
}
x = Math.floor(obj.x);
y = Math.floor(obj.y + obj.height - 1);
if (Math.floor(obj2.x) <= x && x <= Math.floor(obj2.x + obj2.width - 1) &&
Math.floor(obj2.y) <= y && y <= Math.floor(obj2.y + obj2.height - 1))
{
return (4);
}
x = Math.floor(obj2.x + obj2.width - 1);
y = Math.floor(obj2.y);
if (Math.floor(obj.x) <= x && x <= Math.floor(obj.x + obj.width - 1) &&
Math.floor(obj.y) <= y && y <= Math.floor(obj.y + obj.height - 1))
{
return (2);
}
x = Math.floor(obj2.x);
y = Math.floor(obj2.y);
if (Math.floor(obj.x) <= x && x <= Math.floor(obj.x + obj.width - 1) &&
Math.floor(obj.y) <= y && y <= Math.floor(obj.y + obj.height - 1))
{
return (1);
}
x = Math.floor(obj2.x + obj2.width - 1);
y = Math.floor(obj2.y + obj2.height - 1);
if (Math.floor(obj.x) <= x && x <= Math.floor(obj.x + obj.width - 1) &&
Math.floor(obj.y) <= y && y <= Math.floor(obj.y + obj.height - 1))
{
return (4);
}
x = Math.floor(obj2.x);
y = Math.floor(obj2.y + obj2.height - 1);
if (Math.floor(obj.x) <= x && x <= Math.floor(obj.x + obj.width - 1) &&
Math.floor(obj.y) <= y && y <= Math.floor(obj.y + obj.height - 1))
{
return (3);
}
return (0);
}
draw_object(obj:SpecialObject)
{
switch (obj.type)
{
case GameType.GOOMBA:
{
this.goomba.x = Math.floor(obj.x) - Math.floor(this.camera);
this.goomba.y = Math.floor(obj.y);
this.goomba.curr_frame = obj.currFrame;
this.Draw_Image(this.goomba, obj);
break;
}
case GameType.COINBLOCK:
{
this.coinBlock.x = Math.floor(obj.x) - Math.floor(this.camera);
this.coinBlock.y = Math.floor(obj.y);
this.coinBlock.curr_frame = obj.currFrame;
this.Draw_Image(this.coinBlock, obj);
break;
}
case GameType.MUSHROOM:
{
this.mushroom.x = Math.floor(obj.x) - Math.floor(this.camera);
this.mushroom.y = Math.floor(obj.y);
this.mushroom.curr_frame = obj.currFrame;
this.Draw_Image(this.mushroom, obj);
break;
}
case GameType.COIN:
{
this.coin.x = Math.floor(obj.x) - Math.floor(this.camera);
this.coin.y = Math.floor(obj.y);
this.coin.curr_frame = obj.currFrame;
this.Draw_Image(this.coin, obj);
break;
}
case GameType.PLATFORM:
{
this.platform.x = Math.floor(obj.x) - Math.floor(this.camera);
this.platform.y = Math.floor(obj.y);
this.platform.curr_frame = obj.currFrame;
this.Draw_Image(this.platform, obj);
break;
}
case GameType.LAVA:
{
this.lava.x = Math.floor(obj.x) - Math.floor(this.camera);
this.lava.y = Math.floor(obj.y);
this.lava.curr_frame = obj.currFrame;
this.Draw_Image(this.lava, obj);
break;
}
case GameType.FIREBALL:
{
this.fireball.x = Math.floor(obj.x) - Math.floor(this.camera);
this.fireball.y = Math.floor(obj.y);
this.fireball.curr_frame = obj.currFrame;
this.Draw_Image(this.fireball, obj);
break;
}
case GameType.FIRERING:
{
this.firering.x = Math.floor(obj.x) - Math.floor(this.camera);
this.firering.y = Math.floor(obj.y);
this.firering.curr_frame = obj.currFrame;
this.Draw_Image(this.firering, obj);
break;
}
case GameType.BOWSER:
{
this.bowser.x = Math.floor(obj.x) - Math.floor(this.camera);
this.bowser.y = Math.floor(obj.y);
this.bowser.curr_frame = obj.currFrame;
this.Draw_Image(this.bowser, obj);
break;
}
case GameType.BOWSERFIRE:
{
this.bowserfire.x = Math.floor(obj.x) - Math.floor(this.camera);
this.bowserfire.y = Math.floor(obj.y);
this.bowserfire.curr_frame = obj.currFrame;
this.Draw_Image(this.bowserfire, obj);
break;
}
case GameType.TURTLE:
{
this.turtle.x = Math.floor(obj.x) - Math.floor(this.camera);
this.turtle.y = Math.floor(obj.y);
this.turtle.curr_frame = obj.currFrame;
this.Draw_Image(this.turtle, obj);
break;
}
}
}
create_object(type:number, x:number, y:number, height:number, width:number, marioTransparent:boolean,
objectTransparent:boolean, velocity:number, ySpeed:number, state:number)
{
let special = new SpecialObject();
special.type = type;
special.x = x;
special.y = y;
special.height = height;
special.width = width;
special.marioTransparent = marioTransparent;
special.objectTransparent = objectTransparent;
special.alive = true;
special.animator = 0;
special.currFrame = 0;
special.ySpeed = ySpeed;
special.velocity = velocity;
special.state = state;
special.image = null;
this.specialCharacters.push(special);
}
updateList(){
for (let i = 0; i < this.specialCharacters.length; i++)
{
if (this.specialCharacters[i].x < this.camera - (640))
{
this.specialCharacters[i].alive = false;
}
if (!this.specialCharacters[i].alive)
{
this.specialCharacters.splice(i,1);
}
}
}
die(){
if (!this.gameOver)
{
if (this.lives > 0)
{
this.lives--;
this.resetLevel();
this.height = 40;
this.width = 40;
}
else
{
this.gameOver = true;
this.marioY = -500;
this.mario.y = -500;
//GAME OVER
}
}
}
killMario(){
this.dying = true;
this.dyingCounter = 0;
this.dyingX = Math.floor(this.mario.x);
this.dyingY = Math.floor(this.mario.y);
this.marioY = -500;
this.mario.y = -500;
}
loading_screen(){
this.ctx.font = "bold 18px Comic Sans MS";
this.ctx.fillStyle = "#FF0000";
this.ctx.fillText("Loading Level...", 260, 170);
}
win(){
this.gameState = GameState.GAME_STATE_WON;
this.ctx.drawImage(this.winScreen, 0, 0);
this.ctx.font = "bold 18px Comic Sans MS";
this.ctx.fillStyle = "#FF0000";
this.ctx.fillText("Thanks for Playing!", 240, 170);
}
process_collision(obj:SpecialObject, obj2:SpecialObject, direction:number, objnum:number)
{
if (obj.type == GameType.MARIO)
{
if (obj2.type == GameType.PLATFORM)
{
if (direction == 1 || direction == 3)
{
this.marioX = obj2.x - this.width;
this.velocity = 0;
}
if (direction == 2 || direction == 4)
{
this.marioX = obj2.x + obj2.width;
this.velocity = 0;
}
if (direction == 5 || direction == 6)
{
this.marioY = obj2.y + obj2.height;
this.ySpeed = 0;
this.jumpReset = 1;
}
if (obj2.state == 0)
{
if (direction == 7 || direction == 8)
{
this.flying = 0;
this.jumpCounter = 0;
obj2.y = obj.y + obj.height;
}
}
if (obj2.state == 1)
{
if (direction == 7 || direction == 8)
{
this.flying = 0;
this.jumpCounter = 0;
this.ySpeed = 0;
this.marioY = obj2.y - this.height;
this.marioX += obj2.velocity;
}
}
if (obj2.state == 2)
{
if (direction == 7 || direction == 8)
{
this.flying = 0;
this.jumpCounter = 0;
this.marioY = obj2.y - this.height + obj2.velocity;
}
}
}
if (obj2.type == GameType.COIN)
{
this.coins++;
obj2.alive = false;
}
if (obj2.type == GameType.MUSHROOM)
{
this.height = this.bigHeight;
obj2.alive = false;
}
if (obj2.type == GameType.FIRERING)
{
if (this.height == this.bigHeight)
{
this.height = 40;
objnum = objnum - obj2.state;
this.specialCharacters[objnum].alive = false;
this.specialCharacters[objnum + 1].alive = false;
this.specialCharacters[objnum + 2].alive = false;
this.specialCharacters[objnum + 3].alive = false;
this.specialCharacters[objnum + 4].alive = false;
}
else
this.killMario();
}
if (obj2.type == GameType.FIREBALL || obj2.type == GameType.BOWSER || obj2.type == GameType.BOWSERFIRE)
{
if (this.height == this.bigHeight)
{
this.height = 40;
obj2.alive = false;
}
else
this.killMario();
}
if (obj2.type == GameType.GOOMBA)
{
if (direction == 7 || direction == 8)
{
this.marioY = obj2.y - this.mario.height;
this.ySpeed = -this.jumpAcceleration;
if (this.isSixtyFPSmode) this.ySpeed*=1.4;
obj2.currFrame = 2;
}
else
{
if (this.height == this.bigHeight)
{
this.height = 40;
obj2.alive = false;
}
else
this.killMario();
}
}
if (obj2.type == GameType.TURTLE)
{
if (direction == 7 || direction == 8)
{
if (obj2.state == 0)
{
this.marioY = obj2.y - this.height;
this.ySpeed = -this.jumpAcceleration;
if (this.isSixtyFPSmode) this.ySpeed*=1.4;
obj2.state = 1;
obj2.velocity = 0;
}
else
{
if (obj2.state == 2)
{
this.marioY = obj2.y - this.height;
this.ySpeed = -this.jumpAcceleration;
if (this.isSixtyFPSmode) this.ySpeed*=1.4;
obj2.state = 1;
obj2.velocity = 0;
}
else
{
if (direction == 7)
{
obj2.state = 2;
obj2.x = this.marioX + this.width;
obj2.velocity = this.maxVelocity * 2;
}
else
{
obj2.state = 2;
obj2.x = this.marioX - obj2.width;
obj2.velocity = -this.maxVelocity * 2;
}
}
}
}
else
{
if (obj2.state == 0 || obj2.state == 2)
{
if (this.height == this.bigHeight)
{
this.height = 40;
obj2.alive = false;
}
else
this.killMario();
}
if (obj2.state == 1)
{
if (direction == 1 || direction == 3 || direction == 5 || direction == 7)
{
obj2.state = 2;
obj2.x = this.marioX + this.width;
obj2.velocity = this.maxVelocity * 2;
}
else
{
obj2.state = 2;
obj2.x = this.marioX - obj2.width;
obj2.velocity = -this.maxVelocity * 2;
}
}
}
}
if (obj2.type == GameType.COINBLOCK)
{
if (direction == 1 || direction == 3)
{
this.marioX = obj2.x - this.width;
this.velocity = 0;
}
if (direction == 2 || direction == 4)
{
this.marioX = obj2.x + obj2.width;
this.velocity = 0;
}
if (direction == 5 || direction == 6)
{
this.marioY = obj2.y + obj2.height;
this.ySpeed = 0;
this.jumpReset = 1;
if (obj2.state == 0)
{
obj2.currFrame = 3;
obj2.state = 1;
if (obj2.velocity == 0)
{
this.coins++;
}
else
{
this.create_object(GameType.MUSHROOM, obj2.x,
obj2.y - 40, 40, 40, false, false, this.mushroomVelocity, 0, 0);
}
this.grid[Math.floor(obj2.y / 40)][Math.floor(obj2.x / 40)] = '8';
}
}
if (direction == 7 || direction == 8)
{
this.marioY = obj2.y - this.height;
this.flying = 0;
this.jumpCounter = 0;
this.ySpeed = 0;
}
}
}
if (obj.type == GameType.GOOMBA)
{
if (obj2.type == GameType.GOOMBA)
{
if (direction == 1 || direction == 3)
{
obj.x = obj2.x - obj.width;
obj.velocity *= -1;
}
if (direction == 2 || direction == 4)
{
obj.x = obj2.x + obj2.width;
obj.velocity *= -1;
}
}
if (obj2.type == GameType.TURTLE)
{
if (obj2.state == 0 || obj2.state == 1)
{
if (direction == 1 || direction == 3)
{
obj.x = obj2.x - obj.width;
obj.velocity *= -1;
}
if (direction == 2 || direction == 4)
{
obj.x = obj2.x + obj2.width;
obj.velocity *= -1;
}
}
else
{
obj.alive = false;
}
}
if (obj2.type == GameType.COINBLOCK || obj2.type == GameType.PLATFORM)
{
if (direction == 1 || direction == 3)
{
obj.x = obj2.x - obj.width;
obj.velocity *= -1;
}
if (direction == 2 || direction == 4)
{
obj.x = obj2.x + obj2.width;
obj.velocity *= -1;
}
if (direction == 7 || direction == 8)
{
obj.y = obj2.y - obj.height;
obj.ySpeed = 0;
}
}
}
if (obj.type == GameType.MUSHROOM)
{
if (obj2.type == GameType.COINBLOCK || obj2.type == GameType.PLATFORM)
{
if (direction == 1 || direction == 3)
{
obj.x = obj2.x - obj.width;
obj.velocity *= -1;
}
if (direction == 2 || direction == 4)
{
obj.x = obj2.x + obj2.width;
obj.velocity *= -1;
}
if (direction == 7 || direction == 8)
{
obj.y = obj2.y - obj.height;
obj.ySpeed = 0;
}
}
}
if (obj.type == GameType.TURTLE)
{
if (obj2.type == GameType.GOOMBA)
{
if (obj.state == 0 || obj.state == 1)
{
if (direction == 1 || direction == 3)
{
obj.x = obj2.x - obj.width;
obj.velocity *= -1;
}
if (direction == 2 || direction == 4)
{
obj.x = obj2.x + obj2.width;
obj.velocity *= -1;
}
}
else
{
obj2.alive = false;
}
}
if (obj2.type == GameType.TURTLE)
{
if (obj2.state == 2 || obj.state == 2)
{
if (obj2.state == 2 && obj.state != 2)
{
obj.alive = false;
}
if (obj2.state != 2 && obj.state == 2)
{
obj2.alive = false;
}
if (obj2.state == 2 && obj.state == 2)
{
obj.alive = false;
obj2.alive = false;
}
}
else
{
if (direction == 1 || direction == 3)
{
obj.x = obj2.x - obj.width;
obj.velocity *= -1;
}
if (direction == 2 || direction == 4)
{
obj.x = obj2.x + obj2.width;
obj.velocity *= -1;
}
}
}
if (obj2.type == GameType.COINBLOCK || obj2.type == GameType.PLATFORM)
{
if (direction == 1 || direction == 3)
{
obj.x = obj2.x - obj.width;
obj.velocity *= -1;
}
if (direction == 2 || direction == 4)
{
obj.x = obj2.x + obj2.width;
obj.velocity *= -1;
}
if (direction == 7 || direction == 8)
{
obj.y = obj2.y - obj.height;
obj.ySpeed = 0;
}
}
}
}
process_object(obj:SpecialObject, objNum:number){
switch (obj.type)
{
case GameType.COINBLOCK:
{
let coin_anim_change = 15;
if (this.isSixtyFPSmode) coin_anim_change = 30;
if (obj.state == 0)
{
if (this.coinAnimator == coin_anim_change)
{
obj.currFrame = 1;
}
if (this.coinAnimator == coin_anim_change*2)
{
obj.currFrame = 2;
}
if (this.coinAnimator == coin_anim_change*3)
{
obj.currFrame = 0;
}
}
break;
}
case GameType.GOOMBA:
{
if (obj.currFrame == 2 && obj.state == 0)
{
obj.animator = 0;
obj.state = 1;
obj.marioTransparent = true;
}
if (obj.state == 0)
{
obj.x += obj.velocity; //move goomba
obj.animator++;
let goomba_anim_switch = 5;
if (this.isSixtyFPSmode) goomba_anim_switch = 10;
if (obj.animator == goomba_anim_switch)
{
if (obj.currFrame == 0)
{
obj.currFrame = 1;
}
else
{
obj.currFrame = 0;
}
obj.animator = 0;
}
//grid coordinates of mario
let xcood:number, xcood2:number, xcood3:number, xcood4:number;
let ycood:number, ycood2:number, ycood3:number, ycood4:number;
xcood = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood2 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood2 = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood3 = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood3 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
xcood4 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood4 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = (xcood * 40) - obj.width;
obj.velocity *= -1;
}
else if (ycood2 >= 0 && ycood2 < this.worldHeight && xcood2 >= 0 && xcood2 < this.worldWidth
&& (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = obj.x - (obj.x % 40) + 40;
obj.velocity *= -1;
}
else if (ycood3 >= 0 && ycood3 < this.worldHeight && xcood3 >= 0 && xcood3 < this.worldWidth
&& (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = (xcood3 * 40) - obj.width;
obj.velocity *= -1;
}
else if (ycood4 >= 0 && ycood4 < this.worldHeight && xcood4 >= 0 && xcood4 < this.worldWidth
&& (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = obj.x - (obj.x % 40) + 40;
obj.velocity *= -1;
}
let collisionTest:number;
for (let i = 0; i < this.specialCharacters.length; i++)
{
collisionTest = 0;
if (this.specialCharacters[i].alive && !this.specialCharacters[i].objectTransparent
&& i != objNum)
collisionTest = this.collision_test(obj, this.specialCharacters[i]);
if (collisionTest > 0)
this.process_collision(obj, this.specialCharacters[i], collisionTest, i);
}
obj.ySpeed += this.gravity;
obj.y += obj.ySpeed;
xcood = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood2 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood2 = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood3 = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood3 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
xcood4 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood4 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = obj.y - (obj.y % 40) + 40;
obj.ySpeed = 0;
}
else if (ycood2 >= 0 && ycood2 < this.worldHeight && xcood2 >= 0 && xcood2 < this.worldWidth
&& (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = obj.y - (obj.y % 40) + 40;
obj.ySpeed = 0;
}
else if (ycood3 >= 0 && ycood3 < this.worldHeight && xcood3 >= 0 && xcood3 < this.worldWidth
&& (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = (ycood3 * 40) - obj.height;
obj.ySpeed = 0;
}
else if (ycood4 >= 0 && ycood4 < this.worldHeight && xcood4 >= 0 && xcood4 < this.worldWidth
&& (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = (ycood4 * 40) - obj.height;
obj.ySpeed = 0;
}
for (let i = 0; i < this.specialCharacters.length; i++)
{
collisionTest = 0;
if (this.specialCharacters[i].alive && !this.specialCharacters[i].objectTransparent && i != objNum)
collisionTest = 4 + this.collision_test(obj, this.specialCharacters[i]);
if (collisionTest > 4)
this.process_collision(obj, this.specialCharacters[i], collisionTest, i);
}
if (obj.y > this.worldHeight * 40)
obj.alive = false;
}
else
{
obj.animator++;
if (obj.animator > 30)
obj.alive = false;
}
break;
}
case GameType.TURTLE:
{
obj.x += obj.velocity; //move turtle
obj.animator++;
let turtle_anim_switch = 5;
if (this.isSixtyFPSmode) turtle_anim_switch = 10;
if (obj.animator == turtle_anim_switch)
{
if (obj.velocity > 0)
{
if (obj.currFrame == 0)
{
obj.currFrame = 1;
}
else
{
obj.currFrame = 0;
}
}
else
{
if (obj.currFrame == 2)
{
obj.currFrame = 3;
}
else
{
obj.currFrame = 2;
}
}
obj.animator = 0;
}
if (obj.state == 1 || obj.state == 2)
{
obj.currFrame = 4;
}
let xcood:number, xcood2:number, xcood3:number, xcood4:number;
let ycood:number, ycood2:number, ycood3:number, ycood4:number;
xcood = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood2 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood2 = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood3 = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood3 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
xcood4 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood4 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = (xcood * 40) - obj.width;
obj.velocity *= -1;
}
else if (ycood2 >= 0 && ycood2 < this.worldHeight && xcood2 >= 0 && xcood2 < this.worldWidth
&& (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = obj.x - (obj.x % 40) + 40;
obj.velocity *= -1;
}
else if (ycood3 >= 0 && ycood3 < this.worldHeight && xcood3 >= 0 && xcood3 < this.worldWidth
&& (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = (xcood3 * 40) - obj.width;
obj.velocity *= -1;
}
else if (ycood4 >= 0 && ycood4 < this.worldHeight && xcood4 >= 0 && xcood4 < this.worldWidth
&& (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = obj.x - (obj.x % 40) + 40;
obj.velocity *= -1;
}
let collisionTest:number;
for (let i = 0; i < this.specialCharacters.length; i++)
{
collisionTest = 0;
if (this.specialCharacters[i].alive && !this.specialCharacters[i].objectTransparent && i != objNum)
collisionTest = this.collision_test(obj, this.specialCharacters[i]);
if (collisionTest > 0)
this.process_collision(obj,this.specialCharacters[i], collisionTest, i);
}
obj.ySpeed += this.gravity;
obj.y += obj.ySpeed;
xcood = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood2 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood2 = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood3 = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood3 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
xcood4 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood4 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = obj.y - (obj.y % 40) + 40;
obj.ySpeed = 0;
}
else if (ycood2 >= 0 && ycood2 < this.worldHeight && xcood2 >= 0 && xcood2 < this.worldWidth
&& (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = obj.y - (obj.y % 40) + 40;
obj.ySpeed = 0;
}
else if (ycood3 >= 0 && ycood3 < this.worldHeight && xcood3 >= 0 && xcood3 < this.worldWidth
&& (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = (ycood3 * 40) - obj.height;
obj.ySpeed = 0;
}
else if (ycood4 >= 0 && ycood4 < this.worldHeight && xcood4 >= 0 && xcood4 < this.worldWidth
&& (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = (ycood4 * 40) - obj.height;
obj.ySpeed = 0;
}
for (let i = 0; i < this.specialCharacters.length; i++)
{
collisionTest = 0;
if (this.specialCharacters[i].alive && !this.specialCharacters[i].objectTransparent && i != objNum)
collisionTest = 4 + this.collision_test(obj, this.specialCharacters[i]);
if (collisionTest > 4)
this.process_collision(obj,this.specialCharacters[i], collisionTest, i);
}
if (obj.y > this.worldHeight * 40)
obj.alive = false;
break;
}
case GameType.BOWSER:
{
let fire_anim = 20;
let turnaround_anim = 41;
let yspeed_state = 40;
let reset_state = 81;
let randstate = 90;
let randanim = 50;
if (this.isSixtyFPSmode)
{
fire_anim*=2;
turnaround_anim=(2*turnaround_anim) -1;
yspeed_state*=2;
reset_state=(2*reset_state)-1;
randstate*=2;
randanim*=2;
}
if (obj.animator >= 0)
obj.y += obj.velocity;
if (obj.animator == fire_anim)
{
let fire_speed = -3;
if (this.isSixtyFPSmode)
fire_speed = -2;
this.create_object(GameType.BOWSERFIRE, obj.x, obj.y, 20, 40, false, true, fire_speed, 0, 0);
obj.currFrame = 1;
obj.velocity *= -1;
}
if (obj.animator == turnaround_anim)
{
obj.animator = -(Math.floor(Math.random() * randstate));
obj.velocity *= -1;
obj.currFrame = 0;
}
obj.animator++;
if (obj.state >= 0)
obj.x += obj.ySpeed;
if (obj.state == yspeed_state)
{
obj.ySpeed *= -1;
}
if (obj.state == reset_state)
{
obj.ySpeed *= -1;
obj.state = -(Math.floor(Math.random() * randanim));
}
obj.state++;
break;
}
case GameType.BOWSERFIRE:
{
if (obj.animator >= 0)
obj.x += obj.velocity;
if (this.marioY > obj.y)
obj.y += 1;
else
obj.y -= 1;
if (obj.animator == 20)
{
obj.currFrame = 1;
}
if (obj.animator == 41)
{
obj.currFrame = 0;
obj.animator = 0;
}
obj.animator++;
break;
}
case GameType.FIRERING:
{
obj.x = obj.x - obj.velocity;
obj.y = obj.y - obj.ySpeed;
let xTemp = obj.x;
let yTemp = obj.y;
let velocity = 3;
if (this.isSixtyFPSmode)
velocity = 1.5;
obj.x = (xTemp * Math.cos((velocity * (3.14159) / 180))) + (yTemp * Math.sin((velocity * (3.14159) / 180)));
obj.y = -(xTemp * Math.sin((velocity * (3.14159) / 180))) + (yTemp * Math.cos((velocity * (3.14159) / 180)));
obj.x = obj.x + obj.velocity;
obj.y = obj.y + obj.ySpeed;
if (obj.animator == 5)
{
obj.currFrame = 1;
}
if (obj.animator == 10)
{
obj.currFrame = 2;
}
if (obj.animator == 15)
{
obj.currFrame = 3;
}
if (obj.animator == 20)
{
obj.animator = -1;
obj.currFrame = 0;
}
obj.animator++;
break;
}
case GameType.LAVA:
{
if (this.lavaAnimator == 30)
{
obj.currFrame = 0;
}
if (this.lavaAnimator == 60)
{
obj.currFrame = 1;
}
break;
}
case GameType.FIREBALL:
{
let velMultiplier = 1;
let animMultiplier = 1;
if (this.isSixtyFPSmode)
{
velMultiplier = 0.5;
animMultiplier = 2;
}
if (obj.animator >= 0)
obj.y += obj.velocity * velMultiplier;
if (obj.animator == 14*animMultiplier)
{
obj.velocity *= -1;
obj.currFrame = 0;
}
if (obj.animator == 29*animMultiplier)
{
obj.animator = -(Math.floor(Math.random() * 90*animMultiplier));
obj.velocity *= -1;
obj.currFrame = 1;
}
obj.animator++;
break;
}
case GameType.PLATFORM:
{
if (obj.state == 0)
{
if (obj.y > 500)
obj.alive = false;
}
if (obj.state == 1)
{
obj.x += obj.velocity;
if (obj.animator == this.platformTurnaroundFrames)
{
obj.animator = -1;
obj.velocity *= -1;
}
obj.animator++;
}
if (obj.state == 2)
{
obj.y += obj.velocity;
this.updateMario();
let collisionTest = 0;
collisionTest = 4 + this.collision_test(this.marioObject, obj);
if (collisionTest > 4)
this.process_collision(this.marioObject, obj, collisionTest, objNum);
if (obj.animator == this.platformTurnaroundFrames)
{
obj.animator = -1;
obj.velocity *= -1;
}
obj.animator++;
}
break;
}
case GameType.MUSHROOM:
{
obj.x += obj.velocity; //move goomba
let xcood:number, xcood2:number, xcood3:number, xcood4:number;
let ycood:number, ycood2:number, ycood3:number, ycood4:number;
xcood = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood2 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood2 = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood3 = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood3 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
xcood4 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood4 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = (xcood * 40) - obj.width;
obj.velocity *= -1;
}
else if (ycood2 >= 0 && ycood2 < this.worldHeight && xcood2 >= 0 && xcood2 < this.worldWidth
&& (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = obj.x - (obj.x % 40) + 40;
obj.velocity *= -1;
}
else if (ycood3 >= 0 && ycood3 < this.worldHeight && xcood3 >= 0 && xcood3 < this.worldWidth
&& (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = (xcood3 * 40) - obj.width;
obj.velocity *= -1;
}
else if (ycood4 >= 0 && ycood4 < this.worldHeight && xcood4 >= 0 && xcood4 < this.worldWidth
&& (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.x = obj.x - (obj.x % 40) + 40;
obj.velocity *= -1;
}
let collisionTest;
for (let i = 0; i < this.specialCharacters.length; i++)
{
collisionTest = 0;
if (this.specialCharacters[i].alive && !this.specialCharacters[i].objectTransparent && i != objNum)
collisionTest = this.collision_test(obj, this.specialCharacters[i]);
if (collisionTest > 0)
this.process_collision(obj, this.specialCharacters[i], collisionTest, i);
}
obj.ySpeed += this.gravity;
obj.y += obj.ySpeed;
xcood = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood2 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood2 = Math.floor((obj.y - ((obj.y) % 40)) / 40);
xcood3 = Math.floor((obj.x + obj.width - 1 - ((obj.x + obj.width - 1) % 40)) / 40);
ycood3 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
xcood4 = Math.floor((obj.x - ((obj.x) % 40)) / 40);
ycood4 = Math.floor((obj.y + obj.height - 1 - ((obj.y + obj.height - 1) % 40)) / 40);
if (ycood >= 0 && ycood < this.worldHeight && xcood >= 0 && xcood < this.worldWidth
&& (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood][xcood].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = obj.y - (obj.y % 40) + 40;
obj.ySpeed = 0;
}
else if (ycood2 >= 0 && ycood2 < this.worldHeight && xcood2 >= 0 && xcood2 < this.worldWidth
&& (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood2][xcood2].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = obj.y - (obj.y % 40) + 40;
obj.ySpeed = 0;
}
else if (ycood3 >= 0 && ycood3 < this.worldHeight && xcood3 >= 0 && xcood3 < this.worldWidth
&& (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood3][xcood3].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = (ycood3 * 40) - obj.height;
obj.ySpeed = 0;
}
else if (ycood4 >= 0 && ycood4 < this.worldHeight && xcood4 >= 0 && xcood4 < this.worldWidth
&& (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) > 0 && (this.grid[ycood4][xcood4].charCodeAt(0) - '0'.charCodeAt(0)) < 49)
{
obj.y = (ycood4 * 40) - obj.height;
obj.ySpeed = 0;
}
for (let i = 0; i < this.specialCharacters.length; i++)
{
collisionTest = 0;
if (this.specialCharacters[i].alive && !this.specialCharacters[i].objectTransparent && i != objNum)
collisionTest = 4 + this.collision_test(obj, this.specialCharacters[i]);
if (collisionTest > 4)
this.process_collision(obj, this.specialCharacters[i], collisionTest, i);
}
if (obj.y > this.worldHeight * 40)
obj.alive = false;
break;
}
}
}
}
You can’t perform that action at this time.