---###Project D2###---
--[[
Jan 29th 2010 - Well, another re-write. My fault really, i'm looking back on my code again, lots of smaller issues but i see loads.
Optimizing needs to be done, the engine must be perfect!
]]--
---###All Variables/Loading of Images/Sounds###---
---Load Images/Sounds/Font
emulogic10 = pge.font.load("Content/Fonts/emulogic.ttf", 8, PGE_RAM);
tilesheet = pge.texture.load("Content/GFX/tileset.png", PGE_VRAM);
Jump = pge.wav.load("Content/SFX/jump.wav");
die = pge.wav.load("Content/SFX/die.wav");
smash = pge.wav.load("Content/SFX/smash.wav");
stomp = pge.wav.load("Content/SFX/stomp.wav");
pause = pge.wav.load("Content/SFX/pause.wav");
warning = pge.wav.load("Content/SFX/warning.wav");
gameover = pge.wav.load("Content/SFX/gameover.wav");
kick = pge.wav.load("Content/SFX/kick.wav");
coin = pge.wav.load("Content/SFX/coin.wav");
---Map variables
scr_left = 0;
scr_top = 0;
scrSpeed = 2;
tsize = 16;
screeNum = 0;
maxTilesPerRow = (tilesheet:width() / tsize) - 1;
---Tile constants
QuestionBlock = 4;
BlankBlock = 7;
BrickBlock = 2;
---Player animation Variables
----Animation variables, for our animations
--Constants again, interchange depending on current postition/status.
Right = 1;
Left = 0;
StandingL = 0;
StandingR = 1;
JumpingR = 11;
JumpingL = 12;
WalkingR = 2;
WalkingL = 5;
Dead = 8;
TurningRight = 9;
TurningLeft = 10;
GrapRight = 13;
GrapLeft = 14;
direction = Right; ---current direction
turning = false; --bool for turning, to slow the wlking/running down when changing direction
oldDirection = direction; --holds the last direction the player is moving in each frame;
currentSpirte = StandingR; ---holds the current spirte (where to start clipping from)
---Player Variables
player = {};
MarioAnimRight = {AnimTime = 0, startFrame = WalkingR, endFrame = 5, oldFrame = WalkingR};
MarioAnimLeft = {AnimTime = 0, startFrame = WalkingL, endFrame = 8, oldFrame = WalkingL};
MaxTime = 6;
offset = 0;
motion = false;
--Mario States
Small = 0;
Big = 1;
playerChose = 0; -----temp!!!!!!
---Tables
enemies = {};
coins = {};
checkpoint = {};
animBlocks = {};
miniBlocks = {};
scoreText = {};
flag = {};
---Score text variables
multipler = 1;
scoreCount = 0;
---Create colours
backCol = pge.gfx.createcolor(92, 148, 252);
white = pge.gfx.createcolor(255, 255, 255);
---###Functions###---
--StartUp function, carrys out all the intializing stuff.
function startUp(collisionMap, mapFile, playerImg)
--dofile maps
dofile(collisionMap);
dofile(mapFile);
--Get table lengths
mapX = #map[1];
mapY = #map;
--Load the correct image for the player cose of player, mario/luigi.
if playerChose == 0 then
playerImg = pge.texture.load("Content/GFX/mario.png", PGE_RAM);
elseif playerChose == 1 then
playerImg = pge.texture.load("Content/GFX/luigi.png", PGE_RAM);
end
--loop through collision map, inserting.
for i, row in ipairs(layer2) do
for j, tile in ipairs(row) do
if tile == 3 then
table.insert(enemies, {x = tsize * (j-1), y = (tsize * (i-1))-2, width = tsize, height = 18, speedX = 1, speedY = 0, direction = 0, jump = false, AnimTime = 0, startFrame = 0, endFrame = 2, oldFrame = 0, Type = enemyTypeGoomba, alive = true, counter = 0, moving = true});
--perform clean-up
layer2[i][j] = 0;
end
if tile == 6 then
table.insert(enemies, {x = tsize * (j-1), y = (tsize * (i-1))-8, width = tsize, height = 22, speedX = 1, speedY = 0, direction = 0, oldDirection = 0, jump = false, AnimTime = 0, startFrame = 0, endFrame = 0, oldFrame = currentImg, Type = enemyTypeKoopaGreen, mode = Koopa_Mode_Normal, moving = true, alive = true, counter = 0, update = false, Smoving = false});
--perform clean-up
layer2[i][j] = 0;
end
if tile == 7 then
table.insert(enemies, {x = tsize * (j-1), y = (tsize * (i-1))-8, width = tsize, height = 22, speedX = 1, speedY = 0, direction = 0, oldDirection = 0, jump = false, AnimTime = 0, startFrame = 0, endFrame = 0, oldFrame = currentImg, Type = enemyTypeKoopaRed, mode = Koopa_Mode_Normal, moving = true, alive = true, counter = 0, update = false, Smoving = false});
--perform clean-up
layer2[i][j] = 0;
end
if tile == 5 then
table.insert(checkpoint, {x = tsize * (j-1), done = false});
--perform clean-up
layer2[i][j] = 0;
end
if tile == 8 then
table.insert(coins, {x = tsize * (j-1), y = (tsize * (i-1)), width = 12, height = 16, speedY = 0, AnimTime = 0, startFrame = 0, endFrame = 5, oldFrame = 0, display = true, hit = false, counter = 0});
--perform clean-up
layer2[i][j] = 0;
end
if tile == 9 then
table.insert(player, {x = tsize * (j-1), y = (tsize * (i-1)), img = playerImg, width = 16, height = 16, speedX = 0, speedY = 0, jump = false, dead = false, lives = 3, maxSpeedX = 2, maxSpeedY = 8, coins = 00, score = 0, win = false, state = Small});
--perform clean-up
layer2[i][j] = 0;
end
end
end
--Sort the enemie table by X coordinate, from lowest to highest.
table.sort(enemies,
function(a,b)
return a.x<b.x;
end
);
--Insert flag & animation Blocks
for i, row in ipairs(map) do
for j, tile in ipairs(row) do
if tile.Type == 1 then
table.insert(animBlocks, {x = j, y = i, AnimTime = 0, startFrame = 1, endFrame = 3, oldFrame = 1});
end
if tile.Type == 37 then
table.insert(flag, {x = (tsize * (j-1)) + 7, y = tsize * (i-1), done = false });
--clean-up flag, it'll get blitted later.
map[i][j].Type = 0;
end
end
end
--Make the player fall
fall(player[1]);
end
--Main, where everything is put into place.
function Main()
pge.controls.update();
pge.gfx.startdrawing();
--Update everything!
Player();
--Render everything apart from text
Draw();
--Render text
emulogic10:activate();
emulogic10:print(10, 100, white, "FPS: " ..tostring(current_fps));
emulogic10:print(10, 110, white, "SpeedX: " ..tostring(player[1].speedX));
emulogic10:print(10, 120, white, "Left: " ..tostring(left));
emulogic10:print(10, 130, white, "Right: " ..tostring(right));
-- pge.delay(100000);
pge.gfx.enddrawing();
pge.gfx.swapbuffers();
fps = fps + 1;
end
--Update function, handles all inputting/updating a.i, animation etc.
function Update()
--Updae the Player object
Player();
end
--Draw function, handles all rendering!
function Draw(object, grav)
object = player or object;
grav = 0.35 or grav;
--Draws background
pge.gfx.clearscreen(backCol);
--Activates our tilesheet
tilesheet:activate();
TileOnY = pge.math.floor(scr_top/tsize);
TileOnScreenH = pge.math.floor(TileOnY + 272/tsize+1);
TileOnX = pge.math.floor(scr_left/tsize);
TileOnScreenW = pge.math.floor(TileOnX + 480/tsize+1);
if TileOnScreenW > mapX then
TileOnScreenW = mapX;
end
if TileOnScreenH > mapY then
TileOnScreenH = mapY;
end
local y, x, tile, X, Y;
for y = TileOnY+1,TileOnScreenH do
for x = TileOnX+1,TileOnScreenW do
tile = map[y][x].Type;
--draw tiles
if tile > 0 then
tilesheet:draw(map[y][x].x-tsize-scr_left,map[y][x].y-tsize-scr_top, tsize, tsize, tile * tsize, (pge.math.floor(tile/maxTilesPerRow)) * tsize, tsize, tsize, 0, 255);
end
--Update brick block tiles if hit by small mario
if tile == 4 then
if map[y][x].hit then
map[y][x].speedY = map[y][x].speedY - grav;
map[y][x].y = map[y][x].y - map[y][x].speedY;
end
if map[y][x].y > map[y][x].oldy then
map[y][x].speedY = 0;
map[y][x].y = map[y][x].oldy;
map[y][x].hit = false;
end
end
end
end
--Render the player.
local tempX = pge.math.floor(player[1].x);
player[1].img:activate();
player[1].img:draw(tempX-scr_left, player[1].y-scr_top, player[1].width+offset, (player[1].height), (currentSpirte * player[1].width), 0, player[1].width+offset, (player[1].height));
end
---###General Functions###---
--Player function
function Player(object)
object = player[1] or object;
oldDirection = direction;
local animate = false;
if not object.dead and not object.win then
offset = 0;
if not animate then
if direction == Right then
currentSpirte = StandingR;
elseif direction == Left then
currentSpirte = StandingL;
end
--if jumping then change sprite.
if object.jump then
if direction == Right then
currentSpirte = JumpingR;
offset = 1;
elseif direction == Left then
currentSpirte = JumpingL;
offset = 2;
else
offset = 0;
end
end
else
if object.win then
if direction == Right then
currentSpirte = GrapRight;
elseif direction == Left then
currentSpirte = GrapLeft;
end
elseif object.dead then
currentSpirte = Dead;
end
end
if pge.controls.held(PGE_CTRL_RIGHT) or pge.controls.analogx() > 99 then
direction = Right;
movePlayer(object, 1, 0);
scrSpeed = 2;
if not object.jump and not turning and not object.win then
pge.gfx.animateadvanced(MarioAnimRight, MaxTime, MarioAnimRight, MarioAnimRight, true);
currentSpirte = MarioAnimRight.startFrame;
animate = true;
end
elseif not turning and not object.jump and object.speedX > 0 and direction == Right and not pge.controls.held(PGE_CTRL_RIGHT) or pge.controls.analogx() > 99 then
MaxTime = 8;
object.speedX = object.speedX - 0.1;
object.x = object.x + object.speedX;
fall(object);
pge.gfx.animateadvanced(MarioAnimRight, MaxTime, MarioAnimRight, MarioAnimRight, true);
currentSpirte = MarioAnimRight.startFrame;
animate = true;
end
end
if pge.controls.held(PGE_CTRL_LEFT) or pge.controls.analogx() < -99 then
direction = Left;
movePlayer(object, -1, 0);
if not object.jump and not turning and not object.win then
pge.gfx.animateadvanced(MarioAnimLeft, MaxTime, MarioAnimLeft, MarioAnimLeft, true);
currentSpirte = MarioAnimLeft.startFrame;
animate = true;
end
elseif not turning and not object.jump and object.speedX > 0 and direction == Left and not pge.controls.held(PGE_CTRL_LEFT) or pge.controls.analogx() < -99 then
MaxTime = 8;
object.speedX = object.speedX - 0.1;
object.x = object.x - object.speedX;
fall(object);
pge.gfx.animateadvanced(MarioAnimLeft, MaxTime, MarioAnimLeft, MarioAnimLeft, true);
currentSpirte = MarioAnimLeft.startFrame;
animate = true;
end
if object.speedX <= 0 then
object.speedX = 0;
MaxTime = 6;
end
--if holding the right trigger then change max speed, to fake running.
if pge.controls.held(PGE_CTRL_RTRIGGER) then
object.maxSpeedX = 3;
scrSpeed = 3;
MaxTime = 3;
else
object.maxSpeedX = 2;
scrSpeed = 2;
MaxTime = 6;
end
if object.speedX > object.maxSpeedX then
object.speedX = object.maxSpeedX;
end
--if changed direction then reset the speed.
if direction ~= oldDirection and not object.jump and object.speedX >= object.maxSpeedX/2 then
turning = true;
end
--if changed direction then reset the speed.
if turning then
object.speedX = object.speedX - 0.4;
--if turning then change to turning sprite
if direction == Left then
currentSpirte = TurningLeft;
elseif direction == Right then
currentSpirte = TurningRight;
end
if object.speedX <= 0 then
turning = false;
object.speedX = 0;
elseif object.maxSpeedX >= 2.5 and object.speedX <= 1 then
turning = false;
object.speedX = 1;
end
end
if pge.controls.pressed(PGE_CTRL_CROSS) and not object.jump then
object.jump = true;
object.speedY = 5;
Jump:play();
if object.maxSpeedX <= 2 then
object.maxSpeedY = 8.5;
else
object.maxSpeedY = 10;
end
end
if pge.controls.held(PGE_CTRL_CROSS) and object.jump and object.speedY > 0 then
object.speedY = object.speedY + 0.05;
end
if object.jump and not object.win then
jump(object);
end
if object.y <= 3 then
object.y = 3;
object.speedY = -0.5;
end
if object.x <= 1 then
object.x = 1;
end
if scr_left > (mapX * tsize - 480) then
scr_left = (mapX * tsize - 480);
end
end
--Move The player, and check collision
function movePlayer(object, dirx, diry, collisionmap, Map)
collisionmap = layer2;
Map = map;
local collideLeft = false;
local collideRight = false;
--update postition
if not object.dead and object.y < 245 then
object.x = object.x + object.speedX * dirx;
if object.speedY > 0 then
object.y = object.y + object.speedY * diry;
elseif object.speedY < 0 then
object.y = object.y - object.speedY * diry;
end
getObjectCorners(object.x, object.y, object);
if (dirx == 1) then
object.speedX = object.speedX + 0.05;
if (collisionmap[down][right] == 0 and collisionmap[up][right] == 0) then
fall(object);
if (object.x-scr_left) > 280 then
scr_left = scr_left + scrSpeed;
end
else
object.x = ((right-1) * tsize) - object.width;
end
end
if (dirx == -1) then
object.speedX = object.speedX + 0.05;
if (collisionmap[down][left] == 0 and collisionmap[up][left] == 0) then
fall(object);
else
object.x = (left * tsize);
end
end
if (diry == 1) then
if (collisionmap[down][left] == 0 and collisionmap[down][right] == 0) then
else
object.y = ((down-1) * tsize) - object.height;
object.jump = false;
object.speedY = 0;
end
end
if (diry == -1) then
if (collisionmap[up][left] == 0 and collisionmap[up][right] == 0) then
else
object.y = (up * tsize);
object.speedY = -1;
end
end
else
object.y = object.y - object.speedY;
end
if (diry == -1) and not object.dead and object.state == Big then
if (collisionmap[up][right] == BrickBlock) then
Map[up][right].Type = 0;
collisionmap[up][right] = 0;
smash:play();
collideRight = true;
elseif (collisionmap[up][left] == BrickBlock) then
Map[up][left].Type = 0;
collisionmap[up][left] = 0;
smash:play();
collideLeft = true;
else
collideLeft = false;
collideRight = false;
end
elseif (diry == -1) and not object.dead and object.state == Small then
if (collisionmap[up][right] == BrickBlock) and not Map[up][right].hit and (collisionmap[up][left] == BrickBlock) and not Map[up][left].hit then
if direction == Right then
Map[up][right].speedY = 3;
Map[up][right].hit = true;
elseif direction == Left then
Map[up][left].speedY = 3;
Map[up][left].hit = true;
end
elseif (collisionmap[up][right] == BrickBlock) and not Map[up][right].hit then
Map[up][right].speedY = 3;
Map[up][right].hit = true;
elseif (collisionmap[up][left] == BrickBlock) and not Map[up][left].hit then
Map[up][left].speedY = 3;
Map[up][left].hit = true;
end
end
if #animBlocks > 0 then
if (diry == -1) and not object.dead and not collideLeft and not collideRight and not Map[up][left].hit and not Map[up][right].hit then
if (collisionmap[up][right] == QuestionBlock) then
Map[up][right].Type = BlankBlock;
collisionmap[up][right] = 1;
table.insert(coins, {x = (tsize * (right-1))+2, y = (tsize * (up-2)), width = 12, height = 16, speedY = 1, AnimTime = 0, startFrame = 0, endFrame = 5, oldFrame = 0, display = true, hit = true, counter = 0});
object.coins = object.coins + 1;
coin:play();
elseif (collisionmap[up][left] == QuestionBlock) then
Map[up][left].Type = BlankBlock;
collisionmap[up][left] = 1;
table.insert(coins, {x = (tsize * (left-1))+2, y = (tsize * (up-2)), width = 12, height = 16, speedY = 1, AnimTime = 0, startFrame = 0, endFrame = 5, oldFrame = 0, display = true, hit = true, counter = 0});
object.coins = object.coins + 1;
coin:play();
end
end
end
--Check if player is tounching the flag
--if object.x >= flag[1].x + 7 then
-- object.win = true;
--end
--Insert miniBlocks in correct places depending on whether the player collides on the right/left underneath side of block.
if collideLeft then
getObjectCorners(object.x, object.y, object);
table.insert(miniBlocks, {x = ((left-1)*tsize), y = (up-2)*tsize, img = miniBlock, speedY = 7, speedX = -0.4}); --top-left
table.insert(miniBlocks, {x = ((left-1)*tsize+10), y = (up-2)*tsize, img = miniBlock, speedY = 7, speedX = 0.4}); --top-right
table.insert(miniBlocks, {x = ((left-1)*tsize+10), y = ((up-1)*tsize-6), img = miniBlock, speedY = 5, speedX = 0.4}); --bottom-right
table.insert(miniBlocks, {x = ((left-1)*tsize), y = ((up-1)*tsize-6), img = miniBlock, speedY = 5, speedX = -0.4}); --bottom-left
elseif collideRight then
getObjectCorners(object.x, object.y, object);
table.insert(miniBlocks, {x = ((right-1)*tsize)-4, y = (up-2)*tsize, img = miniBlock, speedY = 7, speedX = -0.4}); --top-left
table.insert(miniBlocks, {x = ((right-1)*tsize+10)-4, y = (up-2)*tsize, img = miniBlock, speedY = 7, speedX = 0.4}); --top-right
table.insert(miniBlocks, {x = ((right-1)*tsize+10)-4, y = ((up-1)*tsize-6), img = miniBlock, speedY = 5, speedX = 0.4}); --bottom-right
table.insert(miniBlocks, {x = ((right-1)*tsize)-4, y = ((up-1)*tsize-6), img = miniBlock, speedY = 5, speedX = -0.4}); --bottom-left
end
end
--Get object Corners function, used for tile-based collision
function getObjectCorners(x, y, object)
down = pge.math.floor((y + object.height - 1) / tsize)+1;
up = pge.math.floor(y / tsize)+1;
left = pge.math.floor(x / tsize)+1;
right = pge.math.floor((x + object.width) / tsize)+1;
end
--Jump function, makes our player jump.
function jump(object, grav)
if not object.dead then
grav = 0.5 or grav;
else
grav = 0.25;
end
object.speedY = object.speedY - grav;
if (object.speedY < 0) then
movePlayer(object, 0, 1);
elseif (object.speedY > 0) then
movePlayer(object, 0, -1);
end
end
--Fall function, to make the player "fall"
function fall(object, collisionmap)
collisionmap = layer2;
if not object.jump then
getObjectCorners(object.x, object.y +1, object);
if (collisionmap[down][left] == 0 and collisionmap[down][right] == 0) then
object.speedY = -0.5;
object.jump = true;
end
end
end
--Animation function
function pge.gfx.animateadvanced(ATime, MaxTimePerFrame, SFrame, EFrame, Constant)
Constant = Constant; ---wheter to keep doing the animation or not.
local bool = true;
if bool then
ATime.AnimTime = ATime.AnimTime+1; ---increase time.
if ATime.AnimTime >= MaxTimePerFrame then ---if more than MaxTimePerFrame then reset time, add 1 to the startiong frame. hence animation
ATime.AnimTime = 0;
SFrame.startFrame = SFrame.startFrame+1;
if Constant and SFrame.startFrame >= EFrame.endFrame then ---if constant & we've reached the last frame then reset it.
SFrame.startFrame = SFrame.oldFrame;
elseif not Constant then ----if not constant then when anim finishes, stop animating.
ATime.AnimTime = 0;
SFrame.startFrame = -1;
end
end
end
end