You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1689 lines
39 KiB
1689 lines
39 KiB
//
|
|
// Bomber By Kazys Stepanas
|
|
//
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Globals.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global bgCol = CA.B_BLACK;
|
|
global quit = false;
|
|
global lastTouchedBlock = -1;
|
|
global player;
|
|
|
|
global gameLevel = 1;
|
|
|
|
global blocks = table(count = 0);
|
|
global powerups = table(count = 0);
|
|
global enemies = table(count = 0);
|
|
global blockDeadZone = table(x1 = 31, y1 = 8, x2 = 39, y2 = 14);
|
|
global enemyDeadZone = table(x1 = 22, y1 = 7, x2 = 45, y2 = 16);
|
|
|
|
// Thing types.
|
|
global T_Space = 0;
|
|
global T_Player = 1;
|
|
global T_Bomb = 2;
|
|
global T_Explosion = 3;
|
|
global T_Block = 4;
|
|
global T_Grid = 5;
|
|
global T_Powerup = 6;
|
|
global T_Enemy = 7;
|
|
|
|
// Powerup types.
|
|
global PT_Bomb = 1;
|
|
global PT_Size = 2;
|
|
global PT_Life = 3;
|
|
|
|
// Dead zone types.
|
|
global DT_None = 0;
|
|
global DT_Block = 1;
|
|
global DT_Enemy = 2;
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Grid control.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global grid = table(startX = 0, startY = 0, spaceX = 1, spaceY = 1, rows = 0, cols = 0);
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Constants
|
|
//--------------------------------------------------------------------------------------------------
|
|
global screen = table(w = 80, h = 23);
|
|
global statusY = 24;
|
|
|
|
global bombFuse = 1.25;
|
|
global explodeTime = 0.75;
|
|
global explodeCycle = 0.05;
|
|
global maxPlayerBombs = 10;
|
|
global maxPlayerSize = 5;
|
|
global maxPowerups = 20;
|
|
global maxLives = 5;
|
|
global startLives = 3;
|
|
|
|
global scoreBlock = 10;
|
|
global scoreNME = 50;
|
|
|
|
global nmeMoveTime = 1.0;
|
|
global powerupChance = 40;
|
|
global maxLevel = 10;
|
|
global maxBlockHits = 3;
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Graphics
|
|
//--------------------------------------------------------------------------------------------------
|
|
global playerPix = "\2";
|
|
global playerDeadPix = "\5";
|
|
global bombPix = "\15";
|
|
global expPix = "+";
|
|
global gridPix = "\178";
|
|
global block1Pix = "\176";
|
|
global block2Pix = "\177";
|
|
global block3Pix = "\219";
|
|
global nmePix = "\232";
|
|
global lifePix = "\3";
|
|
global bombSizePix = "#";
|
|
global bombExtraPix = "*";
|
|
global spacePix = " ";
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Colours
|
|
//--------------------------------------------------------------------------------------------------
|
|
global bgColour = 0;
|
|
global fgColour = CA.F_RED | CA.F_GREEN;
|
|
|
|
global playerColour = CA.F_GREEN | CA.F_BLUE;// | CA.F_INTENSITY;
|
|
global gridColour = CA.F_RED;
|
|
global blockColour = CA.F_RED | CA.F_GREEN | CA.F_INTENSITY;
|
|
global nmeColour = CA.F_RED | CA.F_BLUE;
|
|
global powerupColour = CA.F_GREEN | CA.F_INTENSITY;
|
|
global puLifeColour = CA.F_RED;
|
|
|
|
global statusColour = CA.F_RED | CA.F_GREEN;
|
|
|
|
global bombColour = CA.F_BLUE | CA.F_INTENSITY;
|
|
global expColourCount = 5;
|
|
global expColours = array(expColourCount);
|
|
|
|
global readyColour = CA.F_RED;
|
|
|
|
expColours[0] = CA.F_RED | CA.F_INTENSITY;
|
|
expColours[1] = CA.F_BLUE|CA.F_RED;
|
|
expColours[2] = CA.F_RED|CA.F_GREEN | CA.F_INTENSITY;
|
|
expColours[3] = CA.F_RED;
|
|
expColours[4] = CA.F_RED|CA.F_GREEN;
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//--------------------------------------------------------------------------------------------------
|
|
global IsPointWithin = function(a_ptx, a_pty, a_rx1, a_ry1, a_rx2, a_ry2)
|
|
{
|
|
return (a_ptx >= a_rx1 and a_ptx <= a_rx2 and a_pty >= a_ry1 and a_pty <= a_ry2);
|
|
};
|
|
|
|
global OverlapRect = function(a_r1x1, a_r1y1, a_r1x2, a_r1y2, a_r2x1, a_r2y1, a_r2x2, a_r2y2)
|
|
{
|
|
// Test one rect against the other.
|
|
if (IsPointWithin(a_r2x1, a_r2y1, a_r1x1, a_r1y1, a_r1x2, a_r1y2) or
|
|
IsPointWithin(a_r2x1, a_r2y2, a_r1x1, a_r1y1, a_r1x2, a_r1y2) or
|
|
IsPointWithin(a_r2x2, a_r2y2, a_r1x1, a_r1y1, a_r1x2, a_r1y2) or
|
|
IsPointWithin(a_r2x2, a_r2y1, a_r1x1, a_r1y1, a_r1x2, a_r1y2))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Test the other rect.
|
|
if (IsPointWithin(a_r1x1, a_r1y1, a_r2x1, a_r2y1, a_r2x2, a_r2y2) or
|
|
IsPointWithin(a_r1x1, a_r1y2, a_r2x1, a_r2y1, a_r2x2, a_r2y2) or
|
|
IsPointWithin(a_r1x2, a_r1y2, a_r2x1, a_r2y1, a_r2x2, a_r2y2) or
|
|
IsPointWithin(a_r1x2, a_r1y1, a_r2x1, a_r2y1, a_r2x2, a_r2y2))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
global ScreenClampX = function(a_x)
|
|
{
|
|
if (a_x < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (a_x >= screen.w)
|
|
{
|
|
return screen.w-1;
|
|
}
|
|
|
|
return a_x;
|
|
};
|
|
|
|
global ScreenClampY = function(a_y)
|
|
{
|
|
if (a_y < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (a_y >= screen.h)
|
|
{
|
|
return screen.h-1;
|
|
}
|
|
|
|
return a_y;
|
|
};
|
|
|
|
global ScreenClamp = function()
|
|
{
|
|
.x = ScreenClampX(.x);
|
|
.y = ScreenClampY(.y);
|
|
};
|
|
|
|
global BombAt = function(a_x, a_y)
|
|
{
|
|
for (i = 0; i < player.nextBomb; i=i+1)
|
|
{
|
|
bomb = player.bombs[i];
|
|
if (bomb.x == a_x and bomb.y == a_y)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
global PointOverlap = function(a_x1, a_y1, a_x2, a_y2)
|
|
{
|
|
return IsPointWithin(.x, .y, a_x1, a_y1, a_x2, a_y2);
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Player object.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global Player = function()
|
|
{
|
|
newPlayer = table(x = -1, y = -1);
|
|
newPlayer.bombSize = 1;
|
|
newPlayer.bombFuse = bombFuse;
|
|
newPlayer.bombs = array(maxPlayerBombs);
|
|
newPlayer.maxBombs = 1;
|
|
newPlayer.nextBomb = 0;
|
|
newPlayer.threadId = -1;
|
|
newPlayer.lastCanMoveThing = null;
|
|
newPlayer.dead = false;
|
|
newPlayer.lives = startLives;
|
|
newPlayer.score = 0;
|
|
newPlayer.threadId = -1;
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.Draw = function()
|
|
{
|
|
CATTRIB(bgColour | playerColour);
|
|
if (!.dead)
|
|
{
|
|
XYTEXT(.x, .y, playerPix);
|
|
}
|
|
else
|
|
{
|
|
XYTEXT(.x, .y, playerDeadPix);
|
|
}
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.DrawStatus = function()
|
|
{
|
|
CATTRIB(bgColour | puLifeColour | CA.F_INTENSITY);
|
|
XYTEXT(0, statusY, format("%s : %d ", lifePix, .lives));
|
|
CATTRIB(bgColour | powerupColour);
|
|
XYTEXT(10, statusY, format("%s : %d ", bombExtraPix, .maxBombs));
|
|
XYTEXT(20, statusY, format("%s : %d ", bombSizePix, .bombSize));
|
|
CATTRIB(bgColour | statusColour);
|
|
XYTEXT(50, statusY, format("Score : %d ", .score));
|
|
};
|
|
|
|
newPlayer.AddScore = function(a_add)
|
|
{
|
|
.score = .score + a_add;
|
|
.DrawStatus();
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.CanMove = function(a_x, a_y)
|
|
{
|
|
thing = GetThingAt(a_x, a_y, false);
|
|
.lastCanMoveThing = thing;
|
|
return thing.type == T_Space or thing.type == T_Explosion or
|
|
thing.type == T_Powerup or thing.type == T_Enemy;
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.Move = function(a_dx, a_dy)
|
|
{
|
|
if (!.dead)
|
|
{
|
|
oldX = .x;
|
|
oldY = .y;
|
|
newX = ScreenClampX(.x + a_dx);
|
|
newY = ScreenClampY(.y + a_dy);
|
|
|
|
if (.CanMove(newX, newY))
|
|
{
|
|
.x = newX;
|
|
.y = newY;
|
|
if (.lastCanMoveThing.type == T_Powerup)
|
|
{
|
|
.lastCanMoveThing.thing.Pickup();
|
|
}
|
|
else if (.lastCanMoveThing.type == T_Explosion or .lastCanMoveThing.type == T_Enemy)
|
|
{
|
|
.Kill();
|
|
}
|
|
|
|
RefreshXY(oldX, oldY);
|
|
RefreshXY(.x, .y);
|
|
}
|
|
}
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.Kill = function()
|
|
{
|
|
.dead = true;
|
|
RefreshXY(.x, .y);
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.DropBomb = function()
|
|
{
|
|
if (!.dead and .nextBomb < .maxBombs and !BombAt(.x, .y))
|
|
{
|
|
newBomb = Bomb(.x, .y, .bombSize, .bombFuse, this);
|
|
.bombs[.nextBomb] = newBomb;
|
|
.nextBomb = .nextBomb + 1;
|
|
newBomb.Draw();
|
|
}
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.FreeBomb = function(a_bomb)
|
|
{
|
|
found = false;
|
|
limit = .nextBomb;
|
|
for (i = 0; i < limit; i=i+1)
|
|
{
|
|
if (.bombs[i] == a_bomb)
|
|
{
|
|
found = true;
|
|
.nextBomb = .nextBomb - 1;
|
|
}
|
|
if (found)
|
|
{
|
|
if (i+1 < limit)
|
|
{
|
|
.bombs[i] = .bombs[i+1];
|
|
}
|
|
else
|
|
{
|
|
.bombs[i] = null;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.StartThread = function()
|
|
{
|
|
this:stateSet(.IdleState);
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.IdleState = function()
|
|
{
|
|
while (!quit)
|
|
{
|
|
pressed = false;
|
|
if (ISPRESSED(38))
|
|
{
|
|
.Move(0, -1);
|
|
pressed = true;
|
|
}
|
|
else if (ISPRESSED(40))
|
|
{
|
|
.Move(0, 1);
|
|
pressed = true;
|
|
}
|
|
else if (ISPRESSED(39))
|
|
{
|
|
.Move(1, 0);
|
|
pressed = true;
|
|
}
|
|
else if (ISPRESSED(37))
|
|
{
|
|
.Move(-1, 0);
|
|
pressed = true;
|
|
}
|
|
else if (ISPRESSED(' '))
|
|
{
|
|
.DropBomb();
|
|
pressed = true;
|
|
}
|
|
|
|
if (pressed)
|
|
{
|
|
sleep(0.075);
|
|
}
|
|
else if (.dead)
|
|
{
|
|
this:stateSet(.DeadState);
|
|
}
|
|
else
|
|
{
|
|
yield();
|
|
}
|
|
}
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.DeadState = function()
|
|
{
|
|
sleep(explodeTime);
|
|
if (.lives > 0)
|
|
{
|
|
.lives = .lives - 1;
|
|
}
|
|
if (.maxBombs > 1)
|
|
{
|
|
.maxBombs = .maxBombs - 1;
|
|
}
|
|
if (.bombSize > 1)
|
|
{
|
|
.bombSize = .bombSize - 1;
|
|
}
|
|
.DrawStatus();
|
|
|
|
while (!quit)
|
|
{
|
|
if (.lives > 0 and ISPRESSED(' '))
|
|
{
|
|
while (!quit)
|
|
{
|
|
pos = .GetStartPos();
|
|
thing = GetThingAt(pos.x, pos.y, false);
|
|
if (thing.type == T_Enemy)
|
|
{
|
|
thing.thing.Kill();
|
|
}
|
|
sleep(0.2);
|
|
|
|
oldX = .x;
|
|
oldY = .y;
|
|
.x = pos.x;
|
|
.y = pos.y;
|
|
|
|
.dead = false;
|
|
RefreshXY(oldX, oldY);
|
|
RefreshXY(.x, .y);
|
|
this:stateSet(.IdleState);
|
|
}
|
|
}
|
|
yield();
|
|
}
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.Overlap = PointOverlap;
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newPlayer.Cheat = function()
|
|
{
|
|
.lives = 5;
|
|
.maxBombs = 10;
|
|
.bombSize = 5;
|
|
.DrawStatus();
|
|
};
|
|
|
|
newPlayer.GetStartPos = function()
|
|
{
|
|
// Position near centre.
|
|
ptx = grid.startX + (grid.rows/2)*grid.spaceX;
|
|
pty = grid.startY + (grid.cols/2)*grid.spaceY;
|
|
return table(x = ptx, y = pty);
|
|
};
|
|
|
|
pos = newPlayer.GetStartPos();
|
|
newPlayer.x = pos.x;
|
|
newPlayer.y = pos.y;
|
|
|
|
newPlayer.Start = function()
|
|
{
|
|
.threadId = this:thread(.StartThread);
|
|
};
|
|
|
|
newPlayer.Stop = function()
|
|
{
|
|
threadKill(.threadId);
|
|
};
|
|
|
|
return newPlayer;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Bomb object.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global Bomb = function(a_x, a_y, a_size, a_fuse, a_owner)
|
|
{
|
|
newBomb = table(x = a_x, y = a_y, size = a_size, fuse = a_fuse, owner = a_owner);
|
|
newBomb.explode = false;
|
|
newBomb.expMinX = 0;
|
|
newBomb.expMaxX = 0;
|
|
newBomb.expMinY = 0;
|
|
newBomb.expMaxY = 0;
|
|
newBomb.visible = true;
|
|
newBomb.threadId = -1;
|
|
|
|
newBomb.CountDown = function()
|
|
{
|
|
this:stateSet(.FuseState);
|
|
};
|
|
|
|
newBomb.Explode = function()
|
|
{
|
|
this:stateSetOnThread(.threadId, .ExplodeState);
|
|
};
|
|
|
|
newBomb.FuseState = function()
|
|
{
|
|
sleep(.fuse);
|
|
this:stateSet(.ExplodeState);
|
|
};
|
|
|
|
newBomb.ExplodeState = function()
|
|
{
|
|
.expMinX = ScreenClampX(.x - .size);
|
|
.expMaxX = ScreenClampX(.x + .size);
|
|
.expMinY = ScreenClampY(.y - .size);
|
|
.expMaxY = ScreenClampY(.y + .size);
|
|
|
|
.explode = true;
|
|
.visible = false;
|
|
.KillStuff();
|
|
.visible = true;
|
|
.Draw();
|
|
count = 1+g_count;
|
|
|
|
inc = explodeCycle/explodeTime;
|
|
for (i = 0; i < explodeTime; i = i + inc)
|
|
{
|
|
sleep(explodeCycle);
|
|
.Draw();
|
|
}
|
|
|
|
.visible = false;
|
|
RefreshRect(.expMinX, .expMinY, .expMaxX - .expMinX + 1, .expMaxY - .expMinY + 1);
|
|
if (.owner != null)
|
|
{
|
|
.owner.FreeBomb(this);
|
|
}
|
|
exit();
|
|
};
|
|
|
|
newBomb.KillStuff = function()
|
|
{
|
|
// Kill stuff.
|
|
for (x = .x; x >= .expMinX; x=x-1)
|
|
{
|
|
if (!.TryKill(GetThingAt(x, .y, true)))
|
|
{
|
|
.expMinX = x;
|
|
break;
|
|
}
|
|
}
|
|
for (x = .x+1; x <= .expMaxX; x=x+1)
|
|
{
|
|
if (!.TryKill(GetThingAt(x, .y, true)))
|
|
{
|
|
.expMaxX = x;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (y = .y; y >= .expMinY; y=y-1)
|
|
{
|
|
if (!.TryKill(GetThingAt(.x, y, true)))
|
|
{
|
|
.expMinY = y;
|
|
break;
|
|
}
|
|
}
|
|
for (y = .y+1; y <= .expMaxY; y=y+1)
|
|
{
|
|
if (!.TryKill(GetThingAt(.x, y, true)))
|
|
{
|
|
.expMaxY = y;
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
newBomb.TryKill = function(a_thing)
|
|
{
|
|
if (a_thing.type == T_Block)
|
|
{
|
|
a_thing.thing.Kill();
|
|
return false;
|
|
}
|
|
else if (a_thing.type == T_Bomb and a_thing.thing != this)
|
|
{
|
|
a_thing.thing.Explode();
|
|
}
|
|
else if (a_thing.type == T_Player or a_thing.type == T_Enemy)
|
|
{
|
|
a_thing.thing.Kill();
|
|
}
|
|
return true;
|
|
};
|
|
|
|
newBomb.Draw = function()
|
|
{
|
|
if (.visible)
|
|
{
|
|
if (.explode)
|
|
{
|
|
CATTRIB(bgColour | expColours[randint(0, expColourCount)]);
|
|
for (x = .expMinX; x <= .expMaxX; x=x+1)
|
|
{
|
|
if (IsSpaceOnGrid(x, .y))
|
|
{
|
|
XYTEXT(x, .y, expPix);
|
|
}
|
|
}
|
|
|
|
for (y = .expMinY; y <= .expMaxY; y=y+1)
|
|
{
|
|
if (IsSpaceOnGrid(.x, y))
|
|
{
|
|
XYTEXT(.x, y, expPix);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CATTRIB(bgColour | bombColour);
|
|
XYTEXT(.x, .y, bombPix);
|
|
}
|
|
}
|
|
};
|
|
|
|
newBomb.Overlap = function(a_x1, a_y1, a_x2, a_y2)
|
|
{
|
|
if (.explode)
|
|
{
|
|
return OverlapRect(.expMinX, .y, .expMaxX, .y+1, a_x1, a_y1, a_x2, a_y2) and OverlapRect(.x, .expMinY, .x+1, .expMaxY, a_x1, a_y1, a_x2, a_y2);
|
|
}
|
|
return IsPointWithin(.x, .y, a_x1, a_y1, a_x2, a_y2);
|
|
};
|
|
|
|
newBomb.FuseThread = function()
|
|
{
|
|
sleep(.fuse);
|
|
.Explode();
|
|
};
|
|
|
|
newBomb.threadId = newBomb:thread(newBomb.CountDown);
|
|
newBomb:thread(newBomb.FuseThread);
|
|
return newBomb;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Block code.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global Block = function(a_x, a_y)
|
|
{
|
|
newBlock = table(x = a_x, y = a_y, visible = true);
|
|
newBlock.hits = 1;
|
|
|
|
newBlock.Draw = function()
|
|
{
|
|
if (.visible)
|
|
{
|
|
CATTRIB(bgColour | blockColour);
|
|
if (.hits == 3)
|
|
{
|
|
XYTEXT(.x, .y, block3Pix);
|
|
}
|
|
else if (.hits == 2)
|
|
{
|
|
XYTEXT(.x, .y, block2Pix);
|
|
}
|
|
else
|
|
{
|
|
XYTEXT(.x, .y, block1Pix);
|
|
}
|
|
}
|
|
};
|
|
|
|
newBlock.Overlap = PointOverlap;
|
|
|
|
newBlock.KillThread = function()
|
|
{
|
|
yield();
|
|
yield();
|
|
if (.visible)
|
|
{
|
|
.visible = false;
|
|
player.AddScore(scoreBlock);
|
|
if (randint(0, 100) < powerupChance)
|
|
{
|
|
AddPowerup(.x, .y);
|
|
}
|
|
}
|
|
};
|
|
|
|
newBlock.Kill = function()
|
|
{
|
|
.hits = .hits - 1;
|
|
if (.hits == 0)
|
|
{
|
|
this:thread(.KillThread);
|
|
}
|
|
RefreshXY(.x, .y);
|
|
};
|
|
|
|
return newBlock;
|
|
};
|
|
|
|
global CreateBlocks = function(a_num)
|
|
{
|
|
global maxBlockHits;
|
|
global blocks = table(count = 0, blocks = array(a_num));
|
|
for (i = 0; i < a_num; i=i+1)
|
|
{
|
|
pos = GetRandomFreePos(DT_Block, true);
|
|
if (pos.x != -1 and pos.y != -1)
|
|
{
|
|
thing = GetThingAt(pos.x, pos.y, false);
|
|
if (thing.type == DT_Block)
|
|
{
|
|
if (thing.thing.hits < maxBlockHits)
|
|
{
|
|
thing.thing.hits = thing.thing.hits + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
blocks.blocks[i] = Block(pos.x, pos.y);
|
|
blocks.count = i;
|
|
}
|
|
}
|
|
}
|
|
blocks.count = a_num;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Powerup.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global Powerup = function(a_x, a_y, a_type)
|
|
{
|
|
newPu = table(x = a_x, y = a_y, type = a_type);
|
|
|
|
if (a_type == PT_Bomb)
|
|
{
|
|
newPu.Draw = function()
|
|
{
|
|
CATTRIB(bgColour | powerupColour);
|
|
XYTEXT(.x, .y, bombExtraPix);
|
|
};
|
|
|
|
newPu.Pickup = function()
|
|
{
|
|
if (player.maxBombs < maxPlayerBombs)
|
|
{
|
|
player.maxBombs = player.maxBombs + 1;
|
|
}
|
|
player.DrawStatus();
|
|
RemovePowerup(this);
|
|
};
|
|
}
|
|
else if (a_type == PT_Size)
|
|
{
|
|
newPu.Draw = function()
|
|
{
|
|
CATTRIB(bgColour | powerupColour);
|
|
XYTEXT(.x, .y, bombSizePix);
|
|
};
|
|
|
|
newPu.Pickup = function()
|
|
{
|
|
if (player.bombSize < maxPlayerSize)
|
|
{
|
|
player.bombSize = player.bombSize + 1;
|
|
}
|
|
player.DrawStatus();
|
|
RemovePowerup(this);
|
|
};
|
|
}
|
|
else if (a_type == PT_Life)
|
|
{
|
|
newPu.Draw = function()
|
|
{
|
|
CATTRIB(bgColour | puLifeColour);
|
|
XYTEXT(.x, .y, lifePix);
|
|
};
|
|
|
|
newPu.Pickup = function()
|
|
{
|
|
if (player.lives < maxLives)
|
|
{
|
|
player.lives = player.lives + 1;
|
|
}
|
|
player.DrawStatus();
|
|
RemovePowerup(this);
|
|
};
|
|
}
|
|
else
|
|
{
|
|
newPu.Draw = function()
|
|
{
|
|
};
|
|
|
|
newPu.Pickup = function()
|
|
{
|
|
RemovePowerup(this);
|
|
};
|
|
}
|
|
|
|
newPu.Overlap = PointOverlap;
|
|
|
|
return newPu;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Powerup management.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global RandomPowerupType = function()
|
|
{
|
|
int = randint(0, 100);
|
|
|
|
if (int < 49)
|
|
{
|
|
return PT_Bomb;
|
|
}
|
|
if (int < 98)
|
|
{
|
|
return PT_Size;
|
|
}
|
|
|
|
return PT_Life;
|
|
};
|
|
|
|
global AddPowerup = function(a_x, a_y)
|
|
{
|
|
if (powerups.count < maxPowerups)
|
|
{
|
|
powerups.powerups[powerups.count] = Powerup(a_x, a_y, RandomPowerupType());
|
|
powerups.count = powerups.count + 1;
|
|
RefreshXY(a_x, a_y);
|
|
}
|
|
};
|
|
|
|
global RemovePowerup = function(a_pu)
|
|
{
|
|
found = false;
|
|
count = powerups.count;
|
|
for (i = 0; i < count; i = i + 1)
|
|
{
|
|
if (powerups.powerups[i] == a_pu)
|
|
{
|
|
found = true;
|
|
powerups.powerups[i] = null;
|
|
powerups.count = powerups.count - 1;
|
|
}
|
|
if (found)
|
|
{
|
|
if (i+1 < count)
|
|
{
|
|
powerups.powerups[i] = powerups.powerups[i+1];
|
|
}
|
|
else
|
|
{
|
|
powerups.powerups[i] = null;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
global InitPowerups = function()
|
|
{
|
|
global powerups = table(count = 0, powerups = array(maxPowerups));
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Enemies.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global CreateEnemies = function(a_num)
|
|
{
|
|
global enemies = table(count = 0, enemies = array(a_num));
|
|
|
|
for (i = 0; i < a_num; i=i+1)
|
|
{
|
|
pos = GetRandomFreePos(DT_Enemy, false);
|
|
if (pos.x != -1 and pos.y != -1)
|
|
{
|
|
enemies.enemies[i] = Enemy(pos.x, pos.y);
|
|
enemies.count = i+1;
|
|
}
|
|
}
|
|
};
|
|
|
|
global Enemy = function(a_x, a_y)
|
|
{
|
|
newEnemy = table(x = a_x, y = a_y, dead = false);
|
|
newEnemy.lastCanMoveThing = null;
|
|
newEnemy.lastPos = table(x = a_x, y = a_y);
|
|
newEnemy.threadId = -1;
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newEnemy.Draw = function()
|
|
{
|
|
if (!.dead)
|
|
{
|
|
CATTRIB(bgColour | nmeColour);
|
|
XYTEXT(.x, .y, nmePix);
|
|
}
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newEnemy.Kill = function()
|
|
{
|
|
player.AddScore(scoreNME);
|
|
.dead = true;
|
|
if (randint(0, 100) < powerupChance)
|
|
{
|
|
AddPowerup(.x, .y);
|
|
}
|
|
RefreshXY(.x, .y);
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newEnemy.Overlap = PointOverlap;
|
|
|
|
//------------------------------------
|
|
// Movement.
|
|
//------------------------------------
|
|
newEnemy.CanMove = function(a_x, a_y)
|
|
{
|
|
if (a_x < 0 or a_x >= screen.w or a_y < 0 or a_y > screen.h)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
thing = GetThingAt(a_x, a_y, false);
|
|
.lastCanMoveThing = thing;
|
|
return thing.type == T_Space or thing.type == T_Exlposion or
|
|
thing.type == T_Powerup or thing.type == T_Player;
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newEnemy.MoveX = function()
|
|
{
|
|
// Is the player on the same column?
|
|
if (.y == player.y)
|
|
{
|
|
// Are we within a grid spacing?
|
|
if (player.x - .x <= grid.spaceX + 1)
|
|
{
|
|
if (.x < player.x)
|
|
{
|
|
start = .x+1;
|
|
end = player.x+1;
|
|
moveX = start;
|
|
}
|
|
else
|
|
{
|
|
start = player.x+1;
|
|
end = .x;
|
|
moveX = end-1;
|
|
}
|
|
// Do we have a clear path.
|
|
moveOk = true;
|
|
for (x = start; moveOk and x < end; x=x+1)
|
|
{
|
|
if (!.CanMove(x, .y))
|
|
{
|
|
moveOk = false;
|
|
}
|
|
}
|
|
if (moveOk and .CanMove(moveX, .y))
|
|
{
|
|
.MoveTo(moveX, .y);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
mx = 1;
|
|
if (player.x < .x)
|
|
{
|
|
mx = -1;
|
|
}
|
|
if ((.x+mx != .lastPos.x or .y != .lastPos.y) and .CanMove(.x+mx, .y))
|
|
{
|
|
.MoveTo(.x+mx, .y);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newEnemy.MoveY = function()
|
|
{
|
|
// Is the player on the same row?
|
|
if (.x == player.x)
|
|
{
|
|
// Are we within a grid spacing?
|
|
if (player.y - .y <= grid.spaceY + 1)
|
|
{
|
|
if (.y < player.y)
|
|
{
|
|
start = .y+1;
|
|
end = player.y+1;
|
|
moveY = start;
|
|
}
|
|
else
|
|
{
|
|
start = player.y+1;
|
|
end = .y;
|
|
moveY = end-1;
|
|
}
|
|
// Do we have a clear path.
|
|
moveOk = true;
|
|
for (y = start; moveOk and y < end; y=y+1)
|
|
{
|
|
if (!.CanMove(.x, y))
|
|
{
|
|
moveOk = false;
|
|
}
|
|
}
|
|
if (moveOk and .CanMove(.x, moveY))
|
|
{
|
|
.MoveTo(.x, moveY);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
my = 1;
|
|
if (player.y < .y)
|
|
{
|
|
my = -1;
|
|
}
|
|
if ((.x != .lastPos.x or .y+my != .lastPos.y) and .CanMove(.x, .y+my))
|
|
{
|
|
.MoveTo(.x, .y+my);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newEnemy.MoveTo = function(a_x, a_y)
|
|
{
|
|
.lastPos.x = .x;
|
|
.lastPos.y = .y;
|
|
|
|
thing = GetThingAt(a_x, a_y, false);
|
|
|
|
.x = a_x;
|
|
.y = a_y;
|
|
|
|
if (thing.type == T_Player)
|
|
{
|
|
player.Kill();
|
|
}
|
|
else if (thing.type == T_Explosion)
|
|
{
|
|
.Kill();
|
|
}
|
|
|
|
RefreshXY(.lastPos.x, .lastPos.y);
|
|
RefreshXY(.x, .y);
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newEnemy.Move = function()
|
|
{
|
|
moved = false;
|
|
if (!player.dead)
|
|
{
|
|
// Try move towards the player.
|
|
preferX = abs(player.x - .x) > abs(player.y - .y);
|
|
if (preferX)
|
|
{
|
|
moved = .MoveX();
|
|
if (!moved)
|
|
{
|
|
moved = .MoveY();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
moved = .MoveY();
|
|
if (!moved)
|
|
{
|
|
moved = .MoveX();
|
|
}
|
|
}
|
|
|
|
// Try move away from the last position.
|
|
if (!moved)
|
|
{
|
|
testX = 2*.x - .lastPos.x;
|
|
testY = 2*.y - .lastPos.y;
|
|
if (.CanMove(testX, testY))
|
|
{
|
|
.MoveTo(testX, testY);
|
|
moved = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!moved and (.lastPos.x != .x or .lastPos.y != .y) and .CanMove(.lastPos.x, .lastPos.y))
|
|
{
|
|
.MoveTo(.lastPos.x, .lastPos.y);
|
|
}
|
|
};
|
|
|
|
//------------------------------------
|
|
// Thread functions and states.
|
|
//------------------------------------
|
|
newEnemy.Start = function()
|
|
{
|
|
.threadId = this:thread(.IdleState);
|
|
};
|
|
|
|
//------------------------------------
|
|
//------------------------------------
|
|
newEnemy.IdleState = function()
|
|
{
|
|
while (!quit and !.dead)
|
|
{
|
|
sleep(nmeMoveTime);
|
|
.Move();
|
|
}
|
|
};
|
|
|
|
newEnemy.Start();
|
|
|
|
return newEnemy;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Refresh functions.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global Refresh = function()
|
|
{
|
|
CATTRIB(bgColour | fgColour);
|
|
CLS();
|
|
|
|
// Draw blocks.
|
|
for (b = 0; b < blocks.count; b=b+1)
|
|
{
|
|
blocks.blocks[b].Draw();
|
|
}
|
|
|
|
// Draw powerups.
|
|
for (p = 0; p < powerups.count; p=p+1)
|
|
{
|
|
powerups.powerups[p].Draw();
|
|
}
|
|
|
|
// Draw enemies.
|
|
for (e = 0; e < enemies.count; e=e+1)
|
|
{
|
|
enemies.enemies[e].Draw();
|
|
}
|
|
|
|
// Draw bombs.
|
|
for (b = 0; b < player.nextBomb; b=b+1)
|
|
{
|
|
player.bombs[b].Draw();
|
|
}
|
|
|
|
player.Draw();
|
|
player.DrawStatus();
|
|
|
|
DrawGrid();
|
|
};
|
|
|
|
global RefreshXY = function(a_x, a_y)
|
|
{
|
|
RefreshRect(a_x, a_y, 1, 1);
|
|
};
|
|
|
|
global RefreshRect = function(a_x, a_y, a_w, a_h)
|
|
{
|
|
// Clear the area.
|
|
xLimit = a_x + a_w;
|
|
yLimit = a_y + a_h;
|
|
CATTRIB(bgColour | fgColour);
|
|
for (x = a_x; x < xLimit; x=x+1)
|
|
{
|
|
for (y = a_y; y < yLimit; y=y+1)
|
|
{
|
|
XYTEXT(x, y, spacePix);
|
|
}
|
|
}
|
|
|
|
// Draw blocks.
|
|
for (b = 0; b < blocks.count; b=b+1)
|
|
{
|
|
blk = blocks.blocks[b];
|
|
if (blk.Overlap(a_x, a_y, xLimit, yLimit))
|
|
{
|
|
blk.Draw();
|
|
}
|
|
}
|
|
|
|
// Draw powerups.
|
|
for (p = 0; p < powerups.count; p=p+1)
|
|
{
|
|
pu = powerups.powerups[p];
|
|
if (pu.Overlap(a_x, a_y, xLimit, yLimit))
|
|
{
|
|
pu.Draw();
|
|
}
|
|
}
|
|
|
|
// Draw enemies.
|
|
for (e = 0; e < enemies.count; e=e+1)
|
|
{
|
|
nme = enemies.enemies[e];
|
|
if (nme.Overlap(a_x, a_y, xLimit, yLimit))
|
|
{
|
|
nme.Draw();
|
|
}
|
|
}
|
|
|
|
// Draw bombs.
|
|
for (b = 0; b < player.nextBomb; b=b+1)
|
|
{
|
|
bomb = player.bombs[b];
|
|
if (bomb.Overlap(a_x, a_y, xLimit, yLimit))
|
|
{
|
|
bomb.Draw();
|
|
}
|
|
}
|
|
|
|
if (player.Overlap(a_x, a_y, xLimit, yLimit))
|
|
{
|
|
player.Draw();
|
|
}
|
|
|
|
DrawGridRect(a_x, a_y, a_w, a_h);
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Grid control.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global Grid = function(a_startX, a_startY, a_spaceX, a_spaceY)
|
|
{
|
|
grid.startX = a_startX;
|
|
grid.startY = a_startY;
|
|
grid.spaceX = a_spaceX;
|
|
grid.spaceY = a_spaceY;
|
|
|
|
grid.rows = (screen.w-grid.startX) / (grid.spaceX + 1);
|
|
grid.cols = (screen.h-grid.startY) / (grid.spaceY + 1);
|
|
|
|
if ((screen.w-grid.startX) % (grid.spaceX + 1) != 0)
|
|
{
|
|
grid.rows = grid.rows + 1;
|
|
}
|
|
|
|
if ((screen.h-grid.startY) % (grid.spaceY + 1) != 0)
|
|
{
|
|
grid.cols = grid.cols + 1;
|
|
}
|
|
};
|
|
|
|
global DrawGrid = function()
|
|
{
|
|
DrawGridRect(0, 0, screen.w, screen.h);
|
|
};
|
|
|
|
global DrawGridRect = function(a_startX, a_startY, a_w, a_h)
|
|
{
|
|
xLimit = a_startX + a_w;
|
|
yLimit = a_startY + a_h;
|
|
CATTRIB(bgColour | gridColour);
|
|
for (x = a_startX; x < xLimit; x=x+1)
|
|
{
|
|
for (y = a_startY; y < yLimit; y=y+1)
|
|
{
|
|
if (!IsSpaceOnGrid(x, y))
|
|
{
|
|
XYTEXT(x, y, gridPix);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
global IsSpaceOnGrid = function(a_x, a_y)
|
|
{
|
|
return (a_x - grid.startX) % (grid.spaceX+1) == 0 or (a_y - grid.startY) % (grid.spaceY+1) == 0;
|
|
};
|
|
|
|
global IsFreePos = function(a_x, a_y, a_allowBlocks)
|
|
{
|
|
thing = GetThingAt(a_x, a_y, true);
|
|
return thing.type == T_Space or (a_allowBlocks and thing.type == T_Block);
|
|
};
|
|
|
|
global GetThingAt = function(a_x, a_y, a_ignoreExplosion)
|
|
{
|
|
if (!IsSpaceOnGrid(a_x, a_y))
|
|
{
|
|
return table(thing = grid, type = T_Grid);
|
|
}
|
|
|
|
// Test blocks
|
|
for (b = 0; b < blocks.count; b=b+1)
|
|
{
|
|
blk = blocks.blocks[b];
|
|
if (blk.visible and blk.x == a_x and blk.y == a_y)
|
|
{
|
|
return table(thing = blk, type = T_Block);
|
|
}
|
|
}
|
|
|
|
// Test enemies.
|
|
for (e = 0; e < enemies.count; e=e+1)
|
|
{
|
|
nme = enemies.enemies[e];
|
|
if (!nme.dead and nme.x == a_x and nme.y == a_y)
|
|
{
|
|
return table(thing = nme, type = T_Enemy);
|
|
}
|
|
}
|
|
|
|
// Test player pos.
|
|
if (!player.dead and a_x == player.x and a_y == player.y)
|
|
{
|
|
return table(thing = player, type = T_Player);
|
|
}
|
|
|
|
// Test bombs.
|
|
for (b = 0; b < player.nextBomb; b=b+1)
|
|
{
|
|
bomb = player.bombs[b];
|
|
if (!bomb.explode)
|
|
{
|
|
if (bomb.x == a_x and bomb.y == a_y)
|
|
{
|
|
return table(thing = bomb, type = T_Bomb);
|
|
}
|
|
}
|
|
else if (!a_ignoreExplosion and bomb.Overlap(a_x, a_y, a_x+1, a_y+1))
|
|
{
|
|
return table(thing = bomb, type = T_Explosion);
|
|
}
|
|
}
|
|
|
|
// Test powerups.
|
|
for (p = 0; p < powerups.count; p=p+1)
|
|
{
|
|
pu = powerups.powerups[p];
|
|
if (pu.x == a_x and pu.y == a_y)
|
|
{
|
|
return table(thing = pu, type = T_Powerup);
|
|
}
|
|
}
|
|
|
|
return table(thing = null, type = T_Space);
|
|
};
|
|
|
|
global InDeadZone = function(a_dtType, a_x, a_y)
|
|
{
|
|
if (a_dtType == DT_Block)
|
|
{
|
|
return IsPointWithin(a_x, a_y, blockDeadZone.x1, blockDeadZone.y1, blockDeadZone.x2, blockDeadZone.y2);
|
|
}
|
|
if (a_dtType == DT_Enemy)
|
|
{
|
|
return IsPointWithin(a_x, a_y, enemyDeadZone.x1, enemyDeadZone.y1, enemyDeadZone.x2, enemyDeadZone.y2);
|
|
}
|
|
return false;
|
|
};
|
|
|
|
global GetRandomFreePos1 = function(a_deadZoneType, a_allowBlocks, a_tries)
|
|
{
|
|
row = randint(0, grid.rows);
|
|
col = randint(0, grid.cols);
|
|
|
|
px = row*grid.spaceX + grid.startX;
|
|
py = col*grid.spaceY + grid.startY;
|
|
|
|
if (a_deadZoneType != DT_None and InDeadZone(a_deadZoneType, px, py))
|
|
{
|
|
return GetRandomFreePos1(a_deadZoneType, a_tries);
|
|
}
|
|
|
|
if (IsFreePos(px, py))
|
|
{
|
|
return table(x = px, y = py);
|
|
}
|
|
|
|
while (py < screen.h)
|
|
{
|
|
py=py+1;
|
|
if ((a_deadZoneType == DT_None or !InDeadZone(a_deadZoneType, px, py)) and IsFreePos(px, py))
|
|
{
|
|
return table(x = px, y = py);
|
|
}
|
|
}
|
|
|
|
if (tries < 5)
|
|
{
|
|
return GetRandomFreePos1(a_tries+1);
|
|
}
|
|
return table(x = -1, y = -1);
|
|
};
|
|
|
|
global GetRandomFreePos = function(a_deadZoneType, a_allowBlocks)
|
|
{
|
|
return GetRandomFreePos1(a_deadZoneType, a_allowBlocks, 0);
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Initialisation.
|
|
//--------------------------------------------------------------------------------------------------
|
|
RenderRect = function(a_rect)
|
|
{
|
|
CATTRIB(bgColour | gridColour);
|
|
for (i = a_rect.x1; i <= a_rect.x2; i=i+1)
|
|
{
|
|
for (j = a_rect.y1; j <= a_rect.y2; j=j+1)
|
|
{
|
|
XYTEXT(i, j, "o");
|
|
}
|
|
}
|
|
};
|
|
|
|
MemThread = function()
|
|
{
|
|
while (!quit)
|
|
{
|
|
CATTRIB(bgColour | statusColour);
|
|
XYTEXT(65, statusY, format("Mem: %d ", sysGetMemoryUsage()));
|
|
sleep(1.0);
|
|
}
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Level thread.
|
|
//--------------------------------------------------------------------------------------------------
|
|
global GameOver = function()
|
|
{
|
|
CATTRIB(bgColour | statusColour);
|
|
CLS();
|
|
|
|
local score = player.score;
|
|
KillAll();
|
|
|
|
sleep(0.3);
|
|
|
|
global quit;
|
|
while (!quit)
|
|
{
|
|
CATTRIB(bgColour | expColours[randint(0, expColourCount)]);
|
|
x = 8;
|
|
y = 8;
|
|
XYTEXT(x, y, "__________________________________________________________"); y=y+1;
|
|
XYTEXT(x, y, " __ __ "); y=y+1;
|
|
XYTEXT(x, y, " / ) / ) "); y=y+1;
|
|
XYTEXT(x, y, " / __ _ _ __ / / __ )__ "); y=y+1;
|
|
XYTEXT(x, y, " / --, / ) / / ) /___) / / | / /___) / )"); y=y+1;
|
|
XYTEXT(x, y, "_(____/___(___(_/_/__/_(___ ____(____/____|/__(___ _/_____"); y=y+1;
|
|
|
|
CATTRIB(bgColour | statusColour);
|
|
XYTEXT(0, statusY, format("Score : %d", score));
|
|
|
|
if (threadTime() < 1000 and ISPRESSED(' '))
|
|
{
|
|
stateSet(TitleScreenState);
|
|
}
|
|
else if (ISPRESSED(27))
|
|
{
|
|
quit = true;
|
|
}
|
|
|
|
sleep(randfloat(0.03, 0.3));
|
|
}
|
|
|
|
global player = null;
|
|
global blocks = null;
|
|
global enemies = null;
|
|
|
|
stateSet(TitleScreenState);
|
|
};
|
|
|
|
global GameState = function()
|
|
{
|
|
global maxLevel;
|
|
global player;
|
|
global blocks;
|
|
global enemies;
|
|
global gameLevel;
|
|
Grid(3, 2, 5, 5);
|
|
if (player == null or player.lives <= 0)
|
|
{
|
|
player = Player();
|
|
}
|
|
pos = player.GetStartPos();
|
|
player.x = pos.x;
|
|
player.y = pos.y;
|
|
|
|
global nmeMoveTime = 1.0 - gameLevel*0.1;
|
|
|
|
InitPowerups();
|
|
CreateBlocks(min(10 + 10*gameLevel, 99));
|
|
CreateEnemies(5*gameLevel);
|
|
yield();
|
|
Refresh();
|
|
|
|
yield();
|
|
player.Start();
|
|
|
|
local done = false;
|
|
while (!quit and !done)
|
|
{
|
|
local count;
|
|
|
|
done = true;
|
|
if (ISPRESSED(27))
|
|
{
|
|
global quit = true;
|
|
break;
|
|
}
|
|
/*
|
|
// Check blocks.
|
|
count = blocks.count;
|
|
for (i = 0; done and i < count; i=i+1)
|
|
{
|
|
blk = blocks.blocks[i];
|
|
if (blk.visible)
|
|
{
|
|
done = false;
|
|
}
|
|
}
|
|
*/
|
|
// Check enemies.
|
|
count = enemies.count;
|
|
for (i = 0; done and i < count; i=i+1)
|
|
{
|
|
nme = enemies.enemies[i];
|
|
if (!nme.dead)
|
|
{
|
|
done = false;
|
|
}
|
|
}
|
|
|
|
// Check bombs.
|
|
done = done and player.nextBomb == 0;
|
|
|
|
// Check for lives.
|
|
done = done or player.lives <= 0;
|
|
|
|
sleep(0.3);
|
|
}
|
|
|
|
player.Stop();
|
|
|
|
if (!quit)
|
|
{
|
|
if (player.lives <= 0)
|
|
{
|
|
stateSet(GameOver);
|
|
}
|
|
global gameLevel;
|
|
gameLevel=gameLevel+1;
|
|
stateSet(LevelState);
|
|
}
|
|
|
|
KillAll();
|
|
};
|
|
|
|
global LevelState = function()
|
|
{
|
|
global maxLevel;
|
|
global gameLevel;
|
|
|
|
if (gameLevel > maxLevel)
|
|
{
|
|
gameLevel = maxLevel;
|
|
}
|
|
|
|
CATTRIB(bgColour | statusColour);
|
|
CLS();
|
|
|
|
sleep(0.3);
|
|
|
|
global quit;
|
|
while (!quit)
|
|
{
|
|
CATTRIB(bgColour | expColours[randint(0, expColourCount)]);
|
|
x = 17;
|
|
y = 8;
|
|
XYTEXT(x, y, "___________________________________________"); y=y+1;
|
|
XYTEXT(x, y, " ____ ___ "); y=y+1;
|
|
XYTEXT(x, y, " / ) / ( ) "); y=y+1;
|
|
XYTEXT(x, y, " /___ / __ __ __ / / "); y=y+1;
|
|
XYTEXT(x, y, " / | /___) / ) / / / / / "); y=y+1;
|
|
XYTEXT(x, y, "_/_____|__(___ _(___(_(___/___(___/__o_____"); y=y+1;
|
|
XYTEXT(x, y, " / "); y=y+1;
|
|
XYTEXT(x, y, " (_ / "); y=y+1;
|
|
|
|
if (threadTime() > 1000 and ISPRESSED(' '))
|
|
{
|
|
CLS();
|
|
sleep(0.5);
|
|
stateSet(GameState);
|
|
}
|
|
else if (ISPRESSED(27))
|
|
{
|
|
quit = true;
|
|
}
|
|
|
|
sleep(randfloat(0.03, 0.3));
|
|
}
|
|
|
|
KillAll();
|
|
};
|
|
|
|
global KillAll = function()
|
|
{
|
|
// Kill all threads.
|
|
global player;
|
|
global enemies;
|
|
global blocks;
|
|
|
|
if (player)
|
|
{
|
|
local count = player.nextBomb;
|
|
for (i = 0; i < count; i=i+1)
|
|
{
|
|
threadKill(player.bombs[i].threadId);
|
|
}
|
|
threadKill(player.threadId);
|
|
}
|
|
|
|
if (enemies)
|
|
{
|
|
count = enemies.count;
|
|
for (i = 0; i < count; i=i+1)
|
|
{
|
|
threadKill(enemies.enemies[i].threadId);
|
|
}
|
|
}
|
|
};
|
|
|
|
global TitleScreenState = function()
|
|
{
|
|
CATTRIB(bgColour | statusColour);
|
|
CLS();
|
|
sleep(0.3);
|
|
while (!quit)
|
|
{
|
|
CATTRIB(bgColour | expColours[randint(0, expColourCount)]);
|
|
x = 17;
|
|
y = 8;
|
|
XYTEXT(x, y, "_________________________________________"); y=y+1;
|
|
XYTEXT(x, y, " ____ "); y=y+1;
|
|
XYTEXT(x, y, " / ) / "); y=y+1;
|
|
XYTEXT(x, y, " /__ / __ _ _ /__ __ )__ "); y=y+1;
|
|
XYTEXT(x, y, " / ) / ) / / ) / ) /___) / )"); y=y+1;
|
|
XYTEXT(x, y, "_/____/___(___/_/_/__/_(___/_(___ _/_____"); y=y+1;
|
|
XYTEXT(x, y, "_________________________________________"); y=y+1;
|
|
|
|
if (ISPRESSED(27))
|
|
{
|
|
global quit = true;
|
|
break;
|
|
}
|
|
else if (ISPRESSED(' '))
|
|
{
|
|
global gameLevel = 1;
|
|
stateSet(LevelState);
|
|
}
|
|
sleep(randfloat(0.03, 0.3));
|
|
}
|
|
|
|
KillAll();
|
|
exit();
|
|
};
|
|
|
|
CURSOR(0, 0); // bool visible, percentage visible
|
|
CATTRIB(fgColour | bgColour);
|
|
|
|
thread(MemThread);
|
|
|
|
quit = false;
|
|
CLS();
|
|
|
|
stateSet(TitleScreenState);
|