Skip to content

Instantly share code, notes, and snippets.

@nonom
Last active April 22, 2018 21:58
Show Gist options
  • Save nonom/9a00215ac37e0ea372d0664f6d456783 to your computer and use it in GitHub Desktop.
Save nonom/9a00215ac37e0ea372d0664f6d456783 to your computer and use it in GitHub Desktop.
// Project: OhNoes
// Created: 2018-03-28
// UDT
Type tCell
x as integer
y as integer
value as integer // Walkable = 0
// Wall = 1
// Room = 2
// Waypoint = 3
EndType
Type tLevel
treasures as tTreasure[MAX_TREASURES_BOXES]
enemies as integer
EndType
Type tTreasure
id as integer
name as string
points as integer
treasureType as integer
EndType
Type tEnemy
spriteId as integer
direction as integer
group as integer
count as integer
collided as integer
debugSprite as integer
x as integer
y as integer
EndType
Type tPlayer
spriteId as integer
direction as integer
x as integer
y as integer
collisionData
EndType
#constant KEY_C 67
#constant keyLeft = GetRawKeyState(37)
#constant keyUp = GetRawKeyState(38)
#constant keyDown = GetRawKeyState(40)
#constant keyRight = GetRawKeyState(39)
#constant keyEsc = GetRawKeyState(27)
#constant MAX_TIME 30
#constant MAX_LEVELS 10
#constant MAX_LIFES 6
#constant CELL_SIZE 16
#constant GAP 4
#constant MAX_TREASURES 20
#constant MAX_TREASURES_BOXES 3
#constant WORLD_SIZE_X 22 // Must match with the static data atm
#constant WORLD_SIZE_Y 14 // TODO: Retrieve dinamically
#constant MAX_ENEMIES = MAX_LEVELS
#constant STATIC_FILE = "static.txt"
#constant MIN_TREASURE_POINTS 10
#constant MAX_TREASURE_POINTS 50
#constant ENEMIES_GROUP 1
#constant WALLS_GROUP 2
#constant TREASURES_GROUP 3
#constant WAYPOINTS_GROUP 4
#constant PATH_GROUP 0
#constant ENEMIES_START_X 1
#constant ENEMIES_START_Y 6
#constant PLAYER_START_X 1
#constant PLAYER_START_Y 1
#constant STARTING_ENEMIES 4 // CHANGE THIS ;)
// The values coming from DATA file
#constant WALL_CELL_TYPE_ID = 1
#constant TREASURE_CELL_TYPE_ID = 2
global gameStatus as integer // 0 = Stopped / 1 = Started / 2 = Ended
global currentPoints as integer
global currentTime as integer
global currentLevel as integer
global currentLifes as integer
global currentScene as integer
global currentEnemies as integer
global worldX as integer
global worldY as integer
global player as tPlayer
global Enemies as tEnemy[]
global staticMap as tCell[WORLD_SIZE_X, WORLD_SIZE_Y]
global levels as tLevel[MAX_LEVELS]
global Treasures as tTreasure[]
global textMenuId as integer
global collision as integer
global collisionData as integer
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle( "OhNoes" )
SetWindowAllowResize( 1 )
SetOrientationAllowed( 1, 1, 1, 1 )
SetSyncRate( 60, 0 )
//SetScissor( 0,0,0,0 )
SetClearColor(55, 15, 0)
worldX = WORLD_SIZE_X * CELL_SIZE
worldY = WORLD_SIZE_Y * CELL_SIZE
SetWindowSize( worldX, worldY , 0 )
SetVirtualResolution( (WORLD_SIZE_X + 1) * CELL_SIZE, (WORLD_SIZE_Y + 1) * CELL_SIZE)
type tButtonType
img as integer //ID of image used
spr as integer //ID of sprite used
state as integer //Button state (1,2,3)
deleted as integer //(0: exists, 1:deleted)
endtype
global GUIButtons as tButtonType[0]
type tDialog
img as integer //ID of image used
spr as integer //ID of sprite used
buttons as tButtonType[0] //IDs of buttons
endtype
AddVirtualButton(1,0, 0, CELL_SIZE)
AddVirtualButton(2,CELL_SIZE * 2, CELL_SIZE, CELL_SIZE)
AddVirtualButton(3,CELL_SIZE * 3, CELL_SIZE, CELL_SIZE)
LoadMusic(1,"Maf464.mp3")
global x as integer
global y as integer
do
PrintStats()
CheckButtons()
// State Machine
select currentScene:
case 0:
// Background
LoadStaticMap()
DrawStaticMap()
currentScene = 1
endcase
case 1:
GetStartMenu()
//TODO DrawBackgroundDemo()
currentScene = 2
endcase
case 2:
if GetRawKeyPressed(KEY_C)
DeleteAllText()
currentScene = 3
endif
endcase
case 3:
// Level loading
currentTime = MAX_TIME
GenerateLevel(currentLevel)
if not currentEnemies
currentEnemies = STARTING_ENEMIES
endif
SpawnEnemies()
SpawnPlayer()
currentScene = 4
endcase
case 4:
UpdateLevel()
endcase
case 4:
if (currentLevel > MAX_LEVELS)
GameEnds()
else
GoNextLevel()
endif
endcase
endselect
if keyEsc // Quie the game after deleting all sprites
DeleteAllSprites()
End
endif
Sync()
loop
Function ToggleWaypoints()
Endfunction
Function CheckButtons()
if GetVirtualButtonPressed(1)
PlayMusic(1)
elseif GetVirtualButtonPressed(2)
StopMusic()
elseif GetVirtualButtonPressed(3)
ToggleWaypoints()
endif
EndFunction
Function UpdateLevel()
UpdateEnemies()
UpdatePlayer()
Endfunction
Function GameEnds()
Endfunction
Function GoNextLevel()
currentLevel = currentLevel + 1
Endfunction
Function UpdatePlayer()
UpdateCollisions()
PlayerController()
//PrintSteps()
EndFunction
function UpdateCollisions()
//Testing
if GetSpriteHitGroup(ENEMIES_GROUP, GetSpriteX(player.spriteId), GetSpriteY(player.spriteId))
//DeleteEnemy(enemy)
//currentEnemies = currentEnemies - 1
currentLifes = currentLifes - 1 // Move to delete enemy insteaed
endif
endfunction
Function UpdateEnemies()
for i=0 to currentEnemies - 1
UpdateEnemy(i)
next
EndFunction
Function SpawnEnemies()
for i=1 to currentEnemies
enemyId = CreateSprite(0)
startX = Floor(CELL_SIZE * ENEMIES_START_X)
startY = Floor(CELL_SIZE * ENEMIES_START_Y)
SetSpriteOffset(enemyId,CELL_SIZE / 2, CELL_SIZE / 2)
SetSpriteColor(enemyId, 255, 255, 0, 255)
SetSpriteSize(enemyId, CELL_SIZE, CELL_SIZE)
SetSpritePosition(enemyId, startX, startY ) // Different start points
//SetSpriteShape ( enemyId, 2 )
SetSpriteGroup(enemyId, ENEMIES_GROUP)
// Creates an enemy
enemy as tEnemy
enemy.spriteId = enemyId
enemy.group = ENEMIES_GROUP // Todo different groups
enemy.count = 0
enemy.collided = 0
enemy.x = startX
enemy.y = startY
enemy.direction = 0 // Up (clockwise 0-3)
Enemies.insert(enemy)
next i
EndFunction
Function SpawnPlayer()
playerId = CreateSprite(0)
xp = CELL_SIZE * PLAYER_START_X
yp = CELL_SIZE * PLAYER_START_Y
SetSpriteColor(playerId, 55, 255, 0, 255)
SetSpriteSize(playerId, CELL_SIZE, CELL_SIZE)
//SetSpriteShape ( playerId, 2 )
SetSpriteOffset(playerId, CELL_SIZE/2, CELL_SIZE/2)
//SetSpriteOffset(playerId, GetSpriteWidth(playerId)/2, GetSpriteHeight(playerId)/2)
SetSpritePosition(playerId, xp, yp )
// Popuplate the global player variable
player.spriteId = playerId
player.x = xp
player.y = yp
player.direction = 0 // Down (clockwise 0-3)
EndFunction
Function GenerateLevel(currentLevel)
level as tLevel
level.enemies = currentLevel
level.treasures = GenerateRandomTreasures()
EndFunction
Function GenerateRandomTreasures()
//Add Treasures
levelTreasures As tTreasure[]
// Adds MAX_TREASURES treasures
for i=1 to MAX_TREASURES_BOXES
commonTreasure As tTreasure
commonTreasure.treasureType = 1
commonTreasure.points = Random(MIN_TREASURE_POINTS, MAX_TREASURE_POINTS)
levelTreasures.insert(commonTreasure)
next i
// Adds a key
keyTreasure As tTreasure
keyTreasure.treasureType = 2
keyTreasure.points = MAX_TREASURE_POINTS
levelTreasures.insert(keyTreasure)
// Adds a tomb
tombTreasure As tTreasure
tombTreasure.treasureType = 3
tombTreasure.points = MAX_TREASURE_POINTS
levelTreasures.insert(tombTreasure)
// Adds a scroll
scrollTreasure As tTreasure
scrollTreasure.treasureType = 4
scrollTreasure.points = MAX_TREASURE_POINTS
levelTreasures.insert(scrollTreasure)
// Adds an extra enemy
enemyTreasure As tTreasure
enemyTreasure.treasureType = 5
enemyTreasure.points = 0
levelTreasures.insert(enemyTreasure)
EndFunction levelTreasures
Function LoadStaticMap()
delimiter$ = ","
dataFile = OpenToRead(STATIC_FILE)
dataLine$ = ReadLine(dataFile)
y as integer = 0
while not FileEOF(dataFile)
for x = 0 to WORLD_SIZE_X
cell as tCell
cell.x = x
cell.y = y
cell.value = Val(GetStringToken(dataLine$, delimiter$, x + 1))
staticMap[x,y] = cell
next x
if y < WORLD_SIZE_Y then inc y else y = 0
dataLine$ = ReadLine(dataFile)
endwhile
EndFunction
Function DrawStaticMap()
for i=0 to WORLD_SIZE_X
for j=0 to WORLD_SIZE_Y
spriteId = CreateSprite(0)
select staticMap[i,j].value
case 0:
SetSpriteColor(spriteId, 0,0,0,255)
endcase
case 1:
SetSpriteColor(spriteId, 255, 125, 0, 255)
SetSpriteGroup(spriteId, WALLS_GROUP)
endcase
case 2:
SetSpriteColor(spriteId, 255, 155, 0, 255)
SetSpriteGroup(spriteId, TREASURES_GROUP)
endcase
case 3:
SetSpriteColor(spriteId, 155, 155, 0, 255)
SetSpriteGroup(spriteId, WAYPOINTS_GROUP)
endcase
endselect
x = i * CELL_SIZE
y = j * CELL_SIZE
//SetSpriteShape ( spriteId, 2 )
SetSpriteSize(spriteId, CELL_SIZE, CELL_SIZE)
SetSpriteOffset(spriteId, CELL_SIZE / 2, CELL_SIZE / 2)
SetSpritePosition(spriteId, x, y)
next j
next i
// For debug purposes
for i=0 to WORLD_SIZE_X
for j=0 to WORLD_SIZE_Y
textId = CreateText(Str(staticMap[i,j].value))
select staticMap[i,j].value
case 1:
SetTextColor(textId, 0,255,255,255)
endcase
case 0:
SetTextColor(textId, 255,255,0,255)
endcase
endselect
x = i * CELL_SIZE
y = j * CELL_SIZE
SetTextPosition(textId, x, y)
SetTextSize(textId, CELL_SIZE)
SetTextAlignment(textId, 0)
next j
next i
EndFunction
Function PrintStats()
PrintC ( "SCORE : " + Str(currentPoints) + " " )
PrintC ( "MEN : " + Str(currentLifes) + " " )
Print ( "FPS : " + Str(Round(ScreenFPS())))
print(x / CELL_SIZE)
print(y / CELL_SIZE)
//print( "Collision: " + str(GetSpriteCollision( sprite[1], sprite[0] )))
//print( "Hit : " + str(GetSpriteHit(x#,y#)))
//Print ("PlayerX: " + Str(player.x))
//Print ("PlayerY: " + Str(player.y))
//Print ("PlayerDirection: " + Str(player.direction))
//Print ("PlayerLifes: " + Str(currentLifes))
//Print ("PlayerCollision: " + Str(collision))
EndFunction
Function GetStartMenu()
textMenuId = CreateText("Press C to Continue")
SetTextPosition(textMenuId, (worldX / 4), worldY / 2)
SetTextColor(textMenuId, 0, 255, 255, 255)
SetTextSize(textMenuId, 18)
if GetRawKeyPressed(KEY_C)
DeleteAllText()
gameStatus = 1
endif
EndFunction
Function UpdateEnemy(i as integer)
MoveEnemy(i)
//OnSeeCreature(enemy, player)
EndFunction
Function MoveEnemy(enemyIndex as integer)
// Get the enemy coordinates
enemyX = GetSpriteX(Enemies[enemyIndex].spriteId)
enemyY = GetSpriteY(Enemies[enemyIndex].spriteId)
// ATM we need to review the outbounds to prevent the walls
if enemyX < CELL_SIZE then enemyX = enemyX + CELL_SIZE
if enemyY < CELL_SIZE then enemyY = enemyY + CELL_SIZE
if enemyX > worldX then enemyX = worldX - CELL_SIZE
if enemyY > worldY then enemyY = worldY - CELL_SIZE
// In every step we need to "see" what cell type is in front of us
x1 = enemyX / CELL_SIZE
y1 = enemyY / CELL_SIZE
//Outbounds nullcheck
if x1 < 1 then x1 = 1
if y1 < 1 then y1 = 1
if x1 > WORLD_SIZE_X then x1 = WORLD_SIZE_X
if y1 > WORLD_SIZE_Y then y1 = WORLD_SIZE_Y
collisionData = staticMap[x1,y1].value
//Print ("CollisionData : " + Str(collisionData))
Enemies[enemyIndex].collided = collisionData
if (Enemies[enemyIndex].x = (x1 * CELL_SIZE)) && (Enemies[enemyIndex].y = (y1 * CELL_SIZE))
select Enemies[enemyIndex].collided
case 3:
repeat
if Random(0, 100) <= 33 // 33% chance to move the direction
Enemies[enemyIndex].direction = Random(0,3)
endif
select(Enemies[enemyIndex].direction)
case 0: //up
y1 = y1 - 1
endcase
case 1: //right
x1 = x1 + 1
endcase
case 2: //down
y1 = y1 + 1
endcase
case 3: //left
x1 = x1 - 1
endcase
endselect
//Outbounds nullchecks again to be safe
if x1 < 1 then x1 = 1
if y1 < 1 then y1 = 1
if x1 > WORLD_SIZE_X then x1 = WORLD_SIZE_X
if y1 > WORLD_SIZE_Y then y1 = WORLD_SIZE_Y
collisionData = staticMap[x1,y1].value
until collisionData = 0 // Ready to go
endcase
endselect
endif
//For debug purposes, uncomment the other debug lines to see it in action
//SetSpritePosition(Enemies[enemyIndex].debugSprite, x1 * CELL_SIZE, y1 * CELL_SIZE)
// Adds an step to the enemy
select(Enemies[enemyIndex].direction)
case 0: //up
enemyY = enemyY - 1
endcase
case 1: //right
enemyX = enemyX + 1
endcase
case 2: //down
enemyY = enemyY + 1
endcase
case 3: //left
enemyX = enemyX - 1
endcase
endselect
Enemies[enemyIndex].x = enemyX
Enemies[enemyIndex].y = enemyY
// Useless atm
if Enemies[enemyIndex].x < CELL_SIZE then Enemies[enemyIndex].x = Enemies[enemyIndex].x + CELL_SIZE
if Enemies[enemyIndex].y < CELL_SIZE then Enemies[enemyIndex].y = Enemies[enemyIndex].x + CELL_SIZE
if Enemies[enemyIndex].x > worldX then Enemies[enemyIndex].x = worldX - CELL_SIZE
if Enemies[enemyIndex].y > worldY then Enemies[enemyIndex].y = worldY - CELL_SIZE
// Finally after a few checs we can move our enemy
SetSpritePosition(Enemies[enemyIndex].spriteId, Enemies[enemyIndex].x, Enemies[enemyIndex].y)
//Print ("EnemyD " + Str(Enemies[enemyIndex].direction))
//Print ("EnemyX " + Str(x1))
//Print ("EnemyY " + Str(y1))
//Print ("EnemyRealX: " + Str(enemyX))
//Print ("EnemyRealY: " + Str(enemyY))
EndFunction
function CheckCollision(player as tPlayer)
// Get the player coordinates
playerX = GetSpriteX(player.spriteId)
playerY = GetSpriteY(player.spriteId)
// ATM we need to review the outbounds to prevent the walls
//if playerX < 0 then playerX = CELL_SIZE
//if playerY < 0 then playerY = CELL_SIZE
//if playerX > worldX then playerX = worldX - CELL_SIZE
//if playerY > worldY then playerY = worldY - CELL_SIZE
// In every step we need to "see" what cell type is in front of us
x1 = Floor(playerX / CELL_SIZE)
y1 = Floor(playerY / CELL_SIZE)
//Outbounds nullcheck
//if x1 < 1 then x1 = 1
//if y1 < 1 then y1 = 1
//if x1 > WORLD_SIZE_X then x1 = WORLD_SIZE_X
//if y1 > WORLD_SIZE_Y then y1 = WORLD_SIZE_Y
select(player.direction)
case 0: //up
y1 = y1
endcase
case 1: //right
x1 = x1 + 1
endcase
case 2: //down
y1 = y1 + 1
endcase
case 3: //left
x1 = x1
endcase
endselect
//Outbounds nullchecks again to be safe
if x1 < 0 then x1 = 0
if y1 < 0 then y1 = 0
if x1 > WORLD_SIZE_X then x1 = WORLD_SIZE_X
if y1 > WORLD_SIZE_Y then y1 = WORLD_SIZE_Y
collisionData = staticMap[x1,y1].value
//Print ("CollisionData : " + Str(collisionData))
player.collisionData = collisionData
remstart
//if (Enemies[enemyIndex].x = (x1 * CELL_SIZE)) && (Enemies[enemyIndex].y = (y1 * CELL_SIZE))
if (player.x = (x1 * CELL_SIZE)) && (player.y = (y1 * CELL_SIZE))
select player.collisionData
case 3, 0:
endcase
endselect
endif
remend
player.x = playerX
player.y = playerY
// Useless atm
//if player.x < CELL_SIZE then player.x = player.x + CELL_SIZE
//if player.y < CELL_SIZE then player.y = player.y + CELL_SIZE
//if player.x > worldX then player.x = worldX - CELL_SIZE
//if player.y > worldY then player.y = worldY - CELL_SIZE
// Finally after a few checs we can move our enemy
//SetSpritePosition(Enemies[enemyIndex].spriteId, Enemies[enemyIndex].x, Enemies[enemyIndex].y)
//Print ("PlayerD " + Str(player.direction))
//Print ("PlayerX " + Str(x1))
//Print ("PlayerY " + Str(y1))
//Print ("PlayerRealX: " + Str(playerX))
//Print ("PlayerRealY: " + Str(playerY))
//Print ("CollisionData: " + Str(collisionData))
//Print ("SpriteX: " + Str(GetSpriteX(player.spriteId)))
//Print ("SpriteY: " + Str(GetSpriteY(player.spriteId)))
//Print ("SpriteOffsetX: " + Str(GetSpriteXByOffset(player.spriteId)))
//Print ("SPriteOffsetY: " + Str(GetSpriteYByOffset(player.spriteId)))
//Print ("XXGetSpriteHit: " + Str(GetSpriteHit(GetSpriteX(player.spriteId), GetSpriteY(player.spriteId))))
//GetSpriteCollision Group
fd = findDistance(player.spriteId)
Print ("DISTANCE: " + Str(fd))
//if not GetSpriteCollision(player.spriteId, hittingSprite) // || not GetSpriteHitGroup(WALLS_GROUP, ox, oy)
collision = 1
if collisionData = 0 or collisionData = 3
//GetSpriteHit(player.x, player.y
collision = 0
endif
endfunction collision
function PlayerController()
if not collision
SetSpritePosition(player.spriteId, player.x, player.y)
x=GetSpriteX( player.spriteId )
y=GetSpriteY( player.spriteId )
endif
currentx = player.x
currenty = player.y
// In this case the movomenet iis only horiz | - vert
if keyLeft
player.direction = 3
if not CheckCollision(player) then player.x = player.x - 1
elseif keyUp
player.direction = 0
if not CheckCollision(player) then player.y = player.y - 1
elseif keyDown
player.direction = 2
if not CheckCollision(player) then player.y = player.y + 1
elseif keyRight
player.direction = 1 // To paint the steps and previee the movements
if not CheckCollision(player) then player.x = player.x + 1
endif
//SetSpritePosition(player.spriteId, (WORLD_SIZE_X - (player.x / CELL_SIZE)) * CELL_SIZE, (WORLD_SIZE_y - (player.y / CELL_SIZE)) * CELL_SIZE)
endfunction
function findDistance(sprite as integer)
gridSize = 16
// Determine which grid square the sprite is in
gridX = Floor(GetSpriteXByOffset(sprite) / WORLD_SIZE_X)
gridY = Floor(GetSpriteYByOffset(sprite) / WORLD_SIZE_Y)
// This determines the left edge of the sprite
x1 = GetSpriteXByOffset(sprite) - (GetSpriteWidth(sprite)/2)
Print (x1)
// This finds the left edge of the grid tile
gx = gridX * gridSize
Print (gx)
// Distance of red line:
d = x1 - gx
Print (d)
endfunction d
// Theme song credits
// https://soundcloud.com/maf464/2006-oh-mummy-theme-maf464-remake
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment