My agk code (not yet finished, need a lot of debug to understand what's wrong.) In fact the original is javascript not c.
// Project: Jeu_bubble_tir
// Created: 19-07-08
// ------------------------------------------------------------------------
// Bubble Shooter Game Tutorial With HTML5 And JavaScript
// Copyright (c) 2015 Rembound.com
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//
// http://rembound.com/articles/bubble-shooter-game-tutorial-with-html5-and-javascript
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
//
// DECLARATIONS
//
// ------------------------------------------------------------------------
#Constant BUBBLE_VITESSE_DEPLACEMENT_BUBBLE 16.0
#Constant BUBBLE_MAX_COLOR 7
#Constant BUBBLE_NOMBRE_RANGEES_DEPART 4
#Constant JEU_INIT 0
#Constant JEU_READY 1
#Constant JEU_SHOOTBUBBLE 2
#Constant JEU_REMOVECLUSTER 3
#Constant JEU_GAMEOVER 4
#Constant TRUE 0
#Constant FALSE 1
// ------------------------------------------------------------------------
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle("Jeu_bubble_tir")
SetWindowSize(1024, 768, 0)
SetWindowAllowResize(1) // allow the user to resize the window
// set display properties
SetVirtualResolution(1024, 768) // doesn't have to match the window
SetOrientationAllowed(1, 1, 1, 1) // allow both portrait and landscape on mobile devices
SetSyncRate(30, 0) // 30fps instead of 60 to save battery
SetScissor(0, 0, 0, 0) // use the maximum available screen space, no black borders
UseNewDefaultFonts(1)
// ------------------------------------------------------------------------
Type Bubble_tile_type
x as Integer
y as Integer
Modele as Integer // type dans le code initial
bRemoved as Integer // removed dans le code initial
Velocite as Integer
bProcessed as integer // processed dans code original
Sprite as Integer
EndType
Type Bubble_coord_type
x as Integer
y as Integer
EndType
Type Bubble_niveau_type
x as Integer // X position
y as Integer // Y position
Largeur as Integer // Width, gets calculated
Hauteur as Integer // Height, gets calculated
Colonnes as Integer // Number of tile columns
Rangees as Integer // Number of tile rows
Largeur_tile as Integer // Visual width of a tile
Hauteur_tile as Integer // Visual height of a tile
Hauteur_rangee as Integer // Height of a row
Rayon as Integer //Bubble collision radius
Tableau_tiles as Bubble_tile_type[100,100] // The two-dimensional tile array
EndType
Global Bubble_niveau as Bubble_niveau_type
Type Bubble_bubble_type
x as Integer
y as Integer
Angle as Integer
Vitesse as Integer
Vitesse_chute as Integer
Modele as Integer
bVisible as Integer
EndType
Type Bubble_bubble_prochaine_type
x as Integer
y as Integer
Modele as Integer
EndType
Type Bubble_joueur_type
x as Integer
y as Integer
Angle as Integer
Modele as Integer
Bubble as Bubble_bubble_type
Prochaine_bubble as Bubble_bubble_prochaine_type
Sprite_bubble as Integer
Sprite_prochaine_bubble as Integer
EndType
Global Bubble_joueur as Bubble_joueur_type
Global Bubble_etat_jeu as Integer // Game states
Global Bubble_score as Integer
Global Bubble_turncounter as Integer
Global Bubble_rowoffset as Integer
Global Bubble_bShowCluster as Integer
Global Bubble_tableau_clusters as Bubble_tile_type[] // Clusters
Global Bubble_tableau_floating_clusters as Bubble_tile_type[-1,-1]
Global Bubble_image as Integer
Global Bubble_cluster as Bubble_tile_type[]
Global Bubble_debug_message as Integer
// ------------------------------------------------------------------------
//
// FUNCTIONS
//
// ------------------------------------------------------------------------
Function Bubble_initialiser_jeu()
Bubble_debug_message = CreateText ("Debug")
SetTextPosition (Bubble_debug_message,10, 600)
SetTextSize (Bubble_debug_message, 30)
Bubble_etat_jeu = JEU_INIT
Bubble_score = 0
Bubble_turncounter = 0
Bubble_rowoffset = 0
Bubble_animation_state = 0
Bubble_animation_time = 0
Bubble_bShowCluster = FALSE
Bubble_tableau_clusters.Length = -1
//bubble_tableau_floating_cluster.Length = -1
// Initialisation du niveau
Bubble_niveau.x = 4
Bubble_niveau.y = 83
Bubble_niveau.Largeur = GetDeviceWidth()
Bubble_niveau.Hauteur = GetDeviceHeight()
Bubble_niveau.Colonnes = 15
Bubble_niveau.Rangees = 16
Bubble_niveau.Largeur_tile = 40
Bubble_niveau.Hauteur_tile = 40
Bubble_niveau.Hauteur_rangee = 34
Bubble_niveau.Rayon = 20
// chargements image
Bubble_image = LoadImage ("boules.png")
// Initialisation du tableau de tiles.
Local i as Integer
Local j as Integer
For i=0 to Bubble_niveau.Colonnes-1
For j=0 To Bubble_niveau.Rangees-1
Local t as Bubble_tile_type
t.x = i
t.y = j
t.Modele = 0
t.bRemoved = FALSE
t.Velocite = 0
t.bProcessed = FALSE
Bubble_niveau.Tableau_tiles[i,j] = t
Next
Next
// Initialisation tiles
Bubble_niveau.Largeur = Bubble_niveau.Colonnes * Bubble_niveau.Largeur_tile + Bubble_niveau.Largeur_tile/2
bubble_niveau_hauteur = (Bubble_niveau.Rangees-1) * Bubble_niveau.Hauteur_rangee + Bubble_niveau.Hauteur_tile
// Initialisation du joueur
Local Joueur_rangee as Integer
Local Joueur_colonne as Integer
Joueur_colonne = Bubble_niveau.Colonnes / 2
Joueur_rangee = Bubble_niveau.Rangees
Local Pos as Bubble_coord_type
Pos = Bubble_GetTileCoordinate (Joueur_colonne, Joueur_rangee)
Bubble_joueur.x = Pos.x
Bubble_joueur.y = Pos.y
Bubble_joueur.Angle = 90
Bubble_joueur.Modele = 0
Bubble_joueur.Prochaine_bubble.x = 800
Bubble_joueur.Prochaine_bubble.y = 100
Local b as Bubble_bubble_type
Local pb as Bubble_bubble_prochaine_type
Bubble_joueur.Angle = 0
Bubble_joueur.Modele = 0
Bubble_joueur.Sprite_bubble = CreateSprite (Bubble_image)
Bubble_joueur.Sprite_prochaine_bubble = CreateSprite (Bubble_image)
SetSpriteOffset (Bubble_joueur.Sprite_bubble, Bubble_niveau.Largeur_tile/2, Bubble_niveau.Hauteur_tile /2)
SetSpriteOffset (Bubble_joueur.Sprite_prochaine_bubble, Bubble_niveau.Largeur_tile/2, Bubble_niveau.Hauteur_tile /2)
SetSpriteDepth (Bubble_joueur.Sprite_bubble, 1)
SetSpriteDepth (Bubble_joueur.Sprite_prochaine_bubble, 1)
SetSpriteAnimation (Bubble_joueur.Sprite_bubble, Bubble_niveau.Largeur_tile, Bubble_niveau.Hauteur_tile, BUBBLE_MAX_COLOR)
SetSpriteAnimation (Bubble_joueur.Sprite_prochaine_bubble, Bubble_niveau.Largeur_tile, Bubble_niveau.Hauteur_tile, BUBBLE_MAX_COLOR)
SetSpritePositionByOffset (Bubble_joueur.Sprite_bubble, Bubble_joueur.x, Bubble_joueur.y)
SetSpritePositionByOffset (Bubble_joueur.Sprite_prochaine_bubble, Bubble_joueur.Prochaine_bubble.x, Bubble_joueur.Prochaine_bubble.y)
b.x = 0
b.y = 0
b.Angle = 0
b.Vitesse = BUBBLE_VITESSE_DEPLACEMENT_BUBBLE
b.Vitesse_chute = 900
b.Modele = 0
b.bVisible = FALSE
Bubble_joueur.Bubble = b
pb.x = 0
pb.y = 0
pb.Modele = 0
Bubble_joueur.Prochaine_bubble = pb
EndFunction
Function Bubble_jouer()
Select Bubble_etat_jeu
Case JEU_INIT
EndCase
Case JEU_READY
//Bubble_render()
Bubble_renderTiles()
Bubble_mouse()
EndCase
Case JEU_SHOOTBUBBLE
Bubble_StateShootBubble()
EndCase
Case JEU_REMOVECLUSTER
Bubble_stateRemoveCluster()
EndCase
Case JEU_GAMEOVER
EndCase
EndSelect
EndFunction
Function Bubble_SetGameState (Etat_jeu as Integer)
Bubble_etat_jeu = Etat_jeu
Bubble_animation_state = 0
Bubble_animationtime = 0
EndFunction
Function Bubble_StateShootBubble()
// Bubble is moving
// Move the bubble in the direction of the mouse
Bubble_joueur.Bubble.Vitesse = BUBBLE_VITESSE_DEPLACEMENT_BUBBLE
Inc Bubble_joueur.Bubble.x, Bubble_joueur.Bubble.Vitesse * Cos (Bubble_joueur.Bubble.Angle)
Inc Bubble_joueur.Bubble.y, Bubble_joueur.Bubble.Vitesse * Sin (Bubble_joueur.Bubble.Angle)
SetSpritePositionByOffset (Bubble_joueur.Sprite_bubble, Bubble_joueur.Bubble.x, Bubble_joueur.Bubble.y)
If Bubble_joueur.bubble.x <= 0 //Bubble_niveau.x
// Left edge
Bubble_joueur.Bubble.Angle = 180 - Bubble_joueur.Bubble.Angle
Bubble_joueur.Bubble.x = 0 //Bubble_niveau.x
Else
If Bubble_joueur.Bubble.x + Bubble_niveau.Largeur_tile >= (Bubble_niveau.Colonnes+1) * Bubble_niveau.Largeur_tile
// Right edge
Bubble_joueur.Bubble.Angle = 180 - Bubble_joueur.Bubble.Angle
Bubble_joueur.Bubble.x = (Bubble_niveau.Colonnes+1) * Bubble_niveau.Largeur_tile - Bubble_niveau.Largeur_tile
Endif
EndIf
// Collisions with the top of the level
If (Bubble_joueur.Bubble.y <= 0)
// Top collision
Bubble_joueur.Bubble.y = 0
Bubble_SnapBubble()
ExitFunction
EndIf
// Collisions with other tiles
Local i as Integer
Local j as Integer
For i=0 to Bubble_niveau.Colonnes-1
For j=0 To Bubble_niveau.Rangees-1
Local tile as Bubble_tile_type
tile = Bubble_niveau.Tableau_tiles[i,j]
If tile.Modele < 0
Continue
EndIf
Local Coord as Bubble_coord_type
Coord = Bubble_GetTileCoordinate (i,j)
If Bubble_determiner_intersection_cercle (Bubble_joueur.Bubble.x + Bubble_niveau.Largeur_tile/2, Bubble_joueur.Bubble.y + Bubble_niveau.Hauteur_tile/2, Bubble_niveau.Rayon, Coord.x + Bubble_niveau.Largeur_tile/2, Coord.y + Bubble_niveau.Hauteur_tile/2, Bubble_niveau.Rayon) = TRUE
// Intersection with a level bubble
Bubble_SnapBubble()
ExitFunction
EndIf
Next
Next
EndFunction
Function Bubble_stateRemoveCluster()
Local i as Integer
Local j as Integer
Local Tile as Bubble_tile_type
Bubble_resetRemoved()
// Mark the tiles as removed
For i=0 to Bubble_tableau_clusters.Length
Bubble_tableau_clusters[i].bRemoved = TRUE
Next
// Find floating clusters
Bubble_tableau_floating_clusters = Bubble_FindFloatingClusters()
// Pop bubbles
Local bTilesLeft as Integer
bTilesleft = FALSE
For i=0 to Bubble_tableau_clusters.Length
Tile = Bubble_tableau_clusters[i]
If Tile.Modele >=0
bTilesLeft = TRUE
Tile.Modele = -1
EndIf
Next
// Drop bubbles
For i=0 to Bubble_tableau_floating_clusters.Length
For j=0 to Bubble_tableau_floating_clusters[i].Length
Tile = Bubble_tableau_floating_clusters[i,j]
If Tile.Modele >= 0
bTileLeft = TRUE
Tile.Modele = -1
EndIf
Next
Next
//
Bubble_RenderTilesAgain()
//
If bTileLeft = FALSE
// Next bubble
Bubble_Nextbubble()
Local bTileFound as Integer
// Check for game over
bTileFound = FALSE
For i=0 To Bubble_niveau.Colonnes-1
For j=0 To Bubble_niveau.Rangees -1
If Bubble_niveau.Tableau_tiles[i,j].Modele <> -1
bTileFound = TRUE
Exit
Endif
Next
Next
If bTileFound = TRUE
Bubble_etat_jeu = JEU_READY
Else
// No tiles left, game over
Bubble_etat_jeu = JEU_GAMEOVER
ExitFunction
Endif
EndIf
EndFunction
Function Bubble_SnapBubble()
// Snap bubble to the grid
Local CenterX as Integer
Local CenterY as Integer
Local GridPos as Bubble_coord_type
// Get the grid position
CenterX = Bubble_joueur.bubble.x + Bubble_niveau.Largeur_tile/2
centerY = Bubble_joueur.bubble.y + Bubble_niveau.Hauteur_tile/2
GridPos = Bubble_GetGridPosition (CenterX, CenterY)
// Make sure the grid position is valid
If GridPos.x <0
GridPos.x = 0
Endif
If GridPos.x >= Bubble_niveau.Colonnes
GridPos.x = Bubble_niveau.Colonnes-1
EndIf
If GridPos.y < 0
GridPos.y = 0
EndIf
If GridPos.y >= Bubble_niveau.Rangees
GridPos.y = Bubble_niveau.Rangees-1
EndIf
// Check if the tile is empty
Local bAjouterTile as Integer
bAjouterTile = FALSE
If Bubble_niveau.Tableau_tiles [Gridpos.x, Gridpos.y].Modele <> -1
// Tile is not empty, shift the new tile downwards
Local Nouvelle_rangee as Integer
For Nouvelle_rangee = Gridpos.y+1 to Bubble_niveau.Rangees-1
If Bubble_niveau.Tableau_tiles [GridPos.x, Nouvelle_rangee].Modele = -1
Gridpos.y = Nouvelle_rangee
bAjouterTile = TRUE
Exit
Endif
Next
Else
bAjouterTile = TRUE
EndIf
// Add the tile to the grid
If bAjouterTile = TRUE
// Hide the player bubble
Bubble_joueur.bubble.bVisible = FALSE
// Set the tile
Bubble_niveau.Tableau_tiles [GridPos.x,GridPos.y].Modele = Bubble_joueur.bubble.Modele
// Find clusters
Bubble_tableau_clusters = Bubble_findCluster (GridPos.x, GridPos.y, TRUE, TRUE, FALSE)
SetTextString (Bubble_debug_message, (str(Bubble_tableau_clusters.Length)))
If Bubble_tableau_clusters.Length >= 3
// Remove the cluster
Bubble_etat_jeu = JEU_REMOVECLUSTER
ExitFunction
EndIf
EndIf
// No clusters found
Inc Bubble_turncounter,1
If Bubble_turncounter >= 3
// Add a row of bubbles
Bubble_addBubbles()
Bubble_turncounter = 0
Bubble_rowoffset = Mod (Bubble_rowoffset+1, 2)
If Bubble_checkGameOver()
ExitFunction
EndIf
EndIf
// re-render all the tiles
Bubble_RenderTilesAgain()
// Next bubble
Bubble_nextBubble()
Bubble_etat_jeu = JEU_READY
EndFunction
Function Bubble_RenderTilesAgain()
Local i as Integer
Local j as Integer
Local Pos as Bubble_coord_type
For i=0 to Bubble_niveau.Colonnes-1
For j=0 To Bubble_niveau.Rangees-1
If Bubble_niveau.Tableau_tiles[i,j].Modele <> -1
Pos = Bubble_GetTileCoordinate (i,j)
If GetSpriteExists(Bubble_niveau.Tableau_tiles[i,j].Sprite)
DeleteSprite(Bubble_niveau.Tableau_tiles[i,j].Sprite)
EndIf
Bubble_niveau.Tableau_tiles[i,j].Sprite = CreateSprite (Bubble_image)
SetSpriteOffset (Bubble_niveau.Tableau_tiles[i,j].Sprite, Bubble_niveau.Largeur_tile/2, Bubble_niveau.Hauteur_tile/2)
SetSpriteDepth (Bubble_niveau.Tableau_tiles[i,j].Sprite,1)
SetSpritePositionByOffset (Bubble_niveau.Tableau_tiles[i,j].Sprite, Pos.x,Pos.Y )
SetSpriteAnimation (Bubble_niveau.Tableau_tiles[i,j].Sprite, Bubble_niveau.Largeur_tile, Bubble_niveau.Hauteur_tile, BUBBLE_MAX_COLOR)
SetSpriteFrame (Bubble_niveau.Tableau_tiles[i,j].Sprite,Bubble_niveau.Tableau_tiles[i,j].Modele+1)
Else
If GetSpriteExists(Bubble_niveau.Tableau_tiles[i,j].Sprite)
DeleteSprite(Bubble_niveau.Tableau_tiles[i,j].Sprite)
EndIf
EndIf
Next
Next
EndFunction
Function Bubble_CheckGameOver()
Local i as Integer
Local Resultat as Integer
// Check for game over
For i=0 To Bubble_niveau.Colonnes-1
// Check if there are bubbles in the bottom row
If Bubble_niveau.Tableau_tiles[i,Bubble_niveau.Rangees-1].Modele <> -1
// Game over
Bubble_NextBubble()
Bubble_etat_jeu = JEU_GAMEOVER
Resultat = TRUE
SetTextString (Bubble_debug_message, "GAME OVER")
ExitFunction Resultat
EndIf
Next
Resultat = FALSE
EndFunction Resultat
Function Bubble_addBubbles()
Local i as Integer
Local j as Integer
Local Modele as Integer
Local Pos as Bubble_coord_type
// Move the rows downwards
For i=0 To Bubble_niveau.Colonnes-1
For j=0 to Bubble_niveau.Rangees-2
Modele = Bubble_niveau.Tableau_tiles[i, Bubble_niveau.Rangees-1-j-1].Modele
Bubble_niveau.Tableau_tiles[i, Bubble_niveau.Rangees-1-j].Modele = Bubble_niveau.Tableau_tiles[i, Bubble_niveau.Rangees-1-j-1].Modele
Next
Next
// Add a new row of bubbles at the top of the rows
For i=0 To Bubble_niveau.Colonnes-1
Modele = Bubble_getExistingColor()
Bubble_niveau.Tableau_tiles[i,0].Modele = Modele
Next
// delete all the displayed tiles
For i=0 to Bubble_niveau.Colonnes-1
For j=0 To Bubble_niveau.Rangees-1
If Bubble_niveau.Tableau_tiles[i,j].Modele <> -1
Pos = Bubble_GetTileCoordinate (i,j)
If GetSpriteExists(Bubble_niveau.Tableau_tiles[i,j].Sprite)
DeleteSprite(Bubble_niveau.Tableau_tiles[i,j].Sprite)
EndIf
EndIf
Next
Next
EndFunction
Function Bubble_findColors()
// Find the remaining colors
Local FoundColors as Integer[]
Local ColorTable as Integer[]
Local i as Integer
Local j as Integer
Local Tile as Bubble_tile_type
For i=0 to BUBBLE_MAX_COLOR-1
ColorTable.Insert (FALSE)
Next
// Check all tiles
For i=0 to Bubble_niveau.Colonnes-1
For j=0 to Bubble_niveau.Rangees-1
Tile = Bubble_niveau.Tableau_tiles[i,j]
If Tile.Modele >=0
If ColorTable[Tile.Modele] = FALSE
ColorTable[Tile.Modele] = TRUE
FoundColors.Insert (Tile.Modele)
EndIf
EndIf
Next
Next
EndFunction FoundColors
Function Bubble_FindCluster (tx as Integer, ty as Integer, MatchType as Integer, Reset as Integer, SkipRemoved as Integer)
// Find cluster at the specified tile location
If Reset = TRUE
// Reset the processed flags
Bubble_resetProcessed()
EndIf
Local Target_tile as Bubble_tile_type
// Get the target tile. Tile coord must be valid.
Target_tile = Bubble_niveau.Tableau_tiles [tx,ty]
// Initialize the toprocess array with the specified tile
Local ToProcess as Bubble_tile_type[]
Local Longueur_tableau_process as Integer
ToProcess.Insert(Target_tile) // contient target_tile
Longueur_tableau_process = 1
Target_tile.bProcessed = TRUE
Local FoundCluster as Bubble_tile_type[]
While (Longueur_tableau_process >= 0)
// Pop the last element from the array
Local CurrentTile as Bubble_tile_type
CurrentTile = ToProcess[ToProcess.Length]
ToProcess.Remove (ToProcess.Length)
Dec Longueur_tableau_process, 1
If CurrentTile.Modele = -1
Continue
EndIf
// Skip tiles with the removed flag
If SkipRemoved = TRUE
If CurrentTile.bRemoved = TRUE
Message ("Skipremoved et Enlevee = true")
Continue
EndIf
EndIf
// Check if current tile has the right type, if matchtype is true
If ((MatchType=FALSE) or (CurrentTile.Modele = Target_tile.Modele))
// Add current tile to the cluster
//Message ("Ajouter tile à cluster")
FoundCluster.Insert (CurrentTile)
// Get the neighbors of the current tile
Local Neighbors as Bubble_tile_type[]
Neighbors = Bubble_getNeighbors(CurrentTile)
// Check the type of each neighbor
For i=0 to Neighbors.Length
If Neighbors[i].bProcessed = FALSE
// Add the neighbor to the toprocess array
ToProcess.Insert (Neighbors[i])
Inc Longueur_tableau_process,1
Neighbors[i].bProcessed = TRUE
EndIf
Next
EndIf
//Message ("Longueur tableau = " + str(ToProcess.Length))
If Longueur_tableau_process <= 0 Then Exit
SetTextString (Bubble_debug_message, str(Longueur_tableau_process))
If Longueur_tableau_process > 300
SetTextString (Bubble_debug_message, "Depassement tableau process -> Exit function.")
Exit
EndIf
EndWhile
// Return the found cluster
EndFunction FoundCluster
Function Bubble_FindFloatingClusters()
Local i as Integer
Local j as Integer
Local k as Integer
// Find floating clusters
// Reset the processed flags
Bubble_resetProcessed()
Local FoundClusters as Bubble_tile_type[-1,-1]
For i=0 To Bubble_niveau.Colonnes-1
For j=0 To Bubble_niveau.Rangees-1
Local Tile as Bubble_tile_type
Tile = Bubble_niveau.Tableau_tiles[i,j]
If Tile.bProcessed = FALSE
// Find all attached tiles
Local FoundCluster as Bubble_tile_type[]
FoundCluster = Bubble_findCluster (i,j,FALSE, FALSE, TRUE)
// There must be a tile in the cluster
If FoundCluster.Length <= 0
continue
EndIf
// Check if the cluster is floating
Local bFloating as Integer
bFloating = TRUE
For k=0 to FoundCluster.Length
// Tile is attached to the roof
If FoundCluster[k].y = 0
bFloating = FALSE
Exit
Endif
Next
If bFloating = TRUE
FoundClusters.Insert (FoundCluster)
EndIf
EndIf
Next
Next
EndFunction FoundClusters
Function Bubble_resetProcessed()
// Reset the processed flags
Local i as Integer
Local j as Integer
Local Index as Integer
For i=0 to Bubble_niveau.Colonnes-1
For j=0 To Bubble_niveau.Rangees-1
Bubble_Niveau.Tableau_tiles[i,j].bProcessed = FALSE
Next
Next
EndFunction
Function Bubble_resetRemoved()
// Reset the removed flags
Local i as Integer
Local j as Integer
For i=0 to Bubble_niveau.Colonnes-1
For j=0 To Bubble_niveau.Rangees-1
Bubble_Niveau.Tableau_tiles[i,j].bRemoved = FALSE
Next
Next
EndFunction
Function Bubble_GetNeighbors (Tile as Bubble_tile_type)
/*
//var neighborsoffsets = [[[1, 0], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1]], // Even row tiles PAIR
// [[1, 0], [1, 1], [0, 1], [-1, 0], [0, -1], [1, -1]]]; // Odd row tiles IMPAIR
function getNeighbors(tile) {
var tilerow = (tile.y + rowoffset) % 2; // Even or odd row
var neighbors = [];
// Get the neighbor offsets for the specified tile
var n = neighborsoffsets[tilerow];
// Get the neighbors
for (var i=0; i<n.length; i++) {
// Neighbor coordinate
var nx = tile.x + n[i][0];
var ny = tile.y + n[i][1];
// Make sure the tile is valid
if (nx >= 0 && nx < level.columns && ny >= 0 && ny < level.rows) {
neighbors.push(level.tiles[nx][ny]);
}
}
return neighbors;
}
*/
// Get the neighbors of the specified tile
Local i as Integer
Local TileRow as Integer
Tilerow = Mod(Tile.y + Bubble_rowoffset,2)
Local Neighbors as Bubble_tile_type[]
Local Neighborsoffsets_x as Integer [6]
Local Neighborsoffsets_y as Integer [6]
Local n_x as Integer
Local n_y as Integer
Select TileRow
Case 0
Neighborsoffsets_x [0] = 1
Neighborsoffsets_x [1] = 0
Neighborsoffsets_x [2] = -1
Neighborsoffsets_x [3] = -1
Neighborsoffsets_x [4] = -1
Neighborsoffsets_x [5] = 0
Neighborsoffsets_y [0] = 0
Neighborsoffsets_y [1] = 1
Neighborsoffsets_y [2] = 1
Neighborsoffsets_y [3] = 0
Neighborsoffsets_y [4] = -1
Neighborsoffsets_y [5] = -1
EndCase
Case 1
Neighborsoffsets_x [0] = 1
Neighborsoffsets_x [1] = 1
Neighborsoffsets_x [2] = 0
Neighborsoffsets_x [3] = -1
Neighborsoffsets_x [4] = 0
Neighborsoffsets_x [5] = 1
Neighborsoffsets_y [0] = 0
Neighborsoffsets_y [1] = 1
Neighborsoffsets_y [2] = 1
Neighborsoffsets_y [3] = 0
Neighborsoffsets_y [4] = -1
Neighborsoffsets_y [5] = -1
EndCase
Case Default
Message ("Error TileRow should be 0 or 1")
EndCase
EndSelect
// Get the neighbor offsets for the specified tile
// Get the neighbors
For i=0 to 5
Local Nx as Integer
Local Ny as Integer
Nx = Tile.x + Neighborsoffsets_x [i]
Ny = (Tile.y) + Neighborsoffsets_y [i]
// Make sure the tile is valid
If Nx > 0
If Nx < Bubble_niveau.Colonnes
If Ny > 0
If Ny <= Bubble_niveau.Rangees
Neighbors.Insert (Bubble_niveau.Tableau_tiles[nx,ny])
local Pos as Bubble_coord_type
Local Col1 as Integer
Local Col2 as Integer
Col1 = MakeColor (255,0,0)
Col2 = MakeColor (255,255,255)
Pos = Bubble_getTileCoordinate (Nx, Ny)
DrawEllipse (Pos.x + Bubble_niveau.Largeur_tile/2, Pos.y + Bubble_niveau.Hauteur_tile/2, 10,10,Col1,Col1,1)
Pos = Bubble_getTileCoordinate (Tile.x, Tile.y)
DrawEllipse (Pos.x + Bubble_niveau.Largeur_tile/2, Pos.y + Bubble_niveau.Hauteur_tile/2, 15,15,Col2,Col2,1)
EndIf
EndIf
Endif
EndIf
Next
EndFunction Neighbors
Function Bubble_renderTiles()
// Render tiles
Local i as Integer
Local j as Integer
// Top to bottom
For j=0 to Bubble_niveau.Rangees-1
For i=0 To Bubble_niveau.Colonnes-1
Local Tile as Bubble_tile_type
// Get the tile
Tile = Bubble_niveau.Tableau_tiles[i,j]
// Calculate the tile coordinates
Local Coord as Bubble_coord_type
Coord = Bubble_GetTileCoordinate (i,j)
// Check if there is a tile present
If Tile.Modele >= 0
// Draw the tile
Bubble_drawBubble (Tile, Coord.x, Coord.y, Tile.Modele)
EndIf
Next
Next
EndFunction
Function Bubble_renderPlayer()
// Render the player bubble
Local CenterX as Integer
Local CenterY as Integer
CenterX = Bubble_joueur.x + Bubble_niveau.Largeur_tile/2
CenterY = Bubble_joueur.y + Bubble_niveau.Hauteur_tile/2
// Draw the angle
Local DestX as Integer
Local DestY as Integer
DestX = CenterX + 1.5 * Bubble_niveau.Largeur_tile * Cos (Bubble_joueur.Angle)
DestY = CenterY + 1.5 * Bubble_niveau.Hauteur_tile * Sin (Bubble_joueur.Angle)
DrawLine (CenterX, CenterY, DestX, DestY, 255,255,255)
// Draw the next bubble
Bubble_joueur.Prochaine_bubble.x = 800
Bubble_joueur.Prochaine_bubble.y = 50
SetSpritePositionByOffset (Bubble_joueur.Sprite_prochaine_bubble, Bubble_joueur.Prochaine_bubble.x, Bubble_joueur.Prochaine_bubble.y)
SetSpriteFrame (Bubble_joueur.Sprite_prochaine_bubble, Bubble_joueur.Prochaine_bubble.Modele+1)
// Draw the bubble
If Bubble_joueur.bubble.bVisible
SetSpriteVisible (Bubble_joueur.Sprite_bubble, TRUE)
SetSpritePositionByOffset (Bubble_joueur.Sprite_bubble, Bubble_joueur.bubble.x, Bubble_joueur.bubble.y)
SetSpriteFrame (Bubble_joueur.Sprite_bubble, Bubble_joueur.Modele+1)
Else
SetSpriteVisible (Bubble_joueur.Sprite_bubble, FALSE)
EndIf
EndFunction
Function Bubble_GetTileCoordinate (Colonne as Integer, Rangee as Integer)
// Get the tile coordinate
Local Tile as Bubble_coord_type
Tile.x = Bubble_niveau.x + Colonne * Bubble_niveau.Largeur_tile
// X offset for odd or even rows
If Mod(Rangee + Bubble_rowoffset,2) = 0
Inc Tile.x, Bubble_niveau.Largeur_tile/2
EndIf
Tile.y = Bubble_niveau.y + Rangee * Bubble_niveau.Hauteur_tile
EndFunction Tile
Function Bubble_GetGridPosition (x as Integer, y as Integer)
Local Grille as Bubble_coord_type
Local xOffset as Integer
// Get the closest grid position
// Grille.y = Floor ( (y - Bubble_niveau.y) / Bubble_niveau.Hauteur_rangee ) Correction a Bubble_niveau.Hauteur_rangee-1
Grille.y = Floor ( (y - Bubble_niveau.y) / Bubble_niveau.Hauteur_rangee-1 )
xOffset = 0
// Check for offset
If Mod (Grille.y + Bubble_rowoffset,2) = 0
xOffset = Bubble_niveau.Largeur_tile / 2
EndIf
Grille.x = Floor ( ((x - xOffset) - Bubble_niveau.x) / Bubble_niveau.Largeur_tile )
EndFunction Grille
Function Bubble_drawBubble (Tile as Bubble_tile_type, x as Integer, y as integer, Frame as Integer)
// Draw the bubble
If Frame <0 or Frame >= BUBBLE_MAX_COLOR
ExitFunction
EndIf
If GetSpriteExists (Tile.Sprite)
SetSpritePositionByOffset (Tile.Sprite, x, y)
SetSpriteFrame (Tile.Sprite, Frame+1)
Endif
EndFunction
Function Bubble_newGame()
// Start a new game
// Reset score
Bubble_score = 0
Bubble_turncounter = 0
Bubble_rowoffset = 0
// Set the gamestate to ready
Bubble_etat_jeu = JEU_READY
// Create the level
Bubble_createLevel()
// Init the next bubble and set the current bubble
Bubble_nextBubble()
Bubble_nextBubble()
EndFunction
Function Bubble_createLevel()
// Create a random level
Local i as Integer
Local j as Integer
Local Count as Integer
Local RandomTile as Integer
Local NewTile as Integer
// Create a level with random tiles
For j=0 to Bubble_niveau.Rangees-1
RandomTile = Random (0, BUBBLE_MAX_COLOR-1)
Count = 0
For i=0 To Bubble_niveau.Colonnes-1
If Count > 2
// Change the random tile
NewTile = Random (0, BUBBLE_MAX_COLOR-1)
// Make sure the new tile is different from the previous tile
If NewTile = RandomTile
NewTile = Mod (NewTile + 1, BUBBLE_MAX_COLOR)
Endif
RandomTile = NewTile
Count = 0
EndIf
Inc Count, 1
If j < BUBBLE_NOMBRE_RANGEES_DEPART //Bubble_niveau.Rangees /2
Bubble_niveau.Tableau_tiles[i,j].Modele = RandomTile
Bubble_niveau.Tableau_tiles[i,j].Sprite = CreateSprite (Bubble_image)
SetSpriteOffset (Bubble_niveau.Tableau_tiles[i,j].Sprite, Bubble_niveau.Largeur_tile/2, Bubble_niveau.Hauteur_tile/2)
SetSpriteDepth (Bubble_niveau.Tableau_tiles[i,j].Sprite,1)
SetSpritePositionByOffset (Bubble_niveau.Tableau_tiles[i,j].Sprite, i,j )
SetSpriteAnimation (Bubble_niveau.Tableau_tiles[i,j].Sprite, Bubble_niveau.Largeur_tile, Bubble_niveau.Hauteur_tile, BUBBLE_MAX_COLOR)
Else
Bubble_niveau.Tableau_tiles[i,j].Modele = -1
Endif
Next
Next
EndFunction
Function Bubble_nextBubble()
// Create a random bubble for the player
// Set the current bubble
Bubble_joueur.Modele = Bubble_joueur.Prochaine_bubble.Modele
Bubble_joueur.Bubble.Modele = Bubble_joueur.Prochaine_bubble.Modele
Bubble_joueur.bubble.x = Bubble_joueur.x
Bubble_joueur.bubble.y = Bubble_joueur.y
SetSpritePositionByOffset (Bubble_joueur.Sprite_bubble, Bubble_joueur.bubble.x, Bubble_joueur.bubble.y)
SetSpriteFrame (Bubble_joueur.Sprite_bubble, Bubble_joueur.Modele+1)
Bubble_joueur.bubble.bVisible = TRUE
// Get a random type from the existing colors
Local NextColor as Integer
Nextcolor = Bubble_getExistingColor()
// Set the next bubble
Bubble_joueur.Prochaine_bubble.Modele = NextColor
EndFunction
Function Bubble_getExistingColor()
// Get a random existing color
Local ExistingColors as Integer[]
Existingcolors = Bubble_FindColors()
Local Bubble_Modele as Integer
BubbleType = 0
If (Existingcolors.Length > 0)
Bubble_Modele = ExistingColors[Random (0, ExistingColors.Length-1)]
EndIf
EndFunction Bubble_Modele
Function Bubble_Shoot_bubble()
// Shoot the bubble
// Shoot the bubble in the direction of the mouse
Bubble_joueur.Bubble.x = Bubble_joueur.x
Bubble_joueur.Bubble.y = Bubble_joueur.y
Bubble_joueur.Bubble.Angle = Bubble_joueur.Angle
Bubble_joueur.Bubble.Modele = Bubble_joueur.Modele
// Set the gamestate
Bubble_etat_jeu = JEU_SHOOTBUBBLE
EndFunction
Function Bubble_determiner_intersection_cercle (x1 as Integer, y1 as Integer, r1 as Integer, x2 as Integer, y2 as Integer, r2 as Integer)
// Check if two circles intersect
Local Resultat as Integer
Local dx as Integer
Local dy as Integer
Local Longueur as Integer
// Calculate the distance between the centers
dx = x1 - x2
dy = y1 - y2
Longueur = sqrt (dx * dx + dy * dy)
If Longueur < r1 + r2
// Circles intersect
Resultat = TRUE
Else
Resultat = FALSE
EndIf
EndFunction Resultat
Function Bubble_Mouse()
Local Pos as Bubble_coord_type
// Get the mouse position
Pos.x = GetRAWMouseX()
Pos.y = GetRAWMouseY()
Local MouseAngle as Integer
// Get the mouse angle
MouseAngle = atan2 ( (Pos.y - Bubble_joueur.y+Bubble_niveau.Hauteur_tile/2), Pos.x - (Bubble_joueur.x + Bubble_niveau.Largeur_tile/2))
// Convert range to 0, 360 degrees
If (MouseAngle < 0)
MouseAngle = 180 + (180 + MouseAngle)
EndIf
SetTextString (Bubble_debug_message, str(MouseAngle))
// Restrict angle
Local lbound as Integer
Local ubound as Integer
lbound = 200
ubound = 340
If MouseAngle < lbound
MouseAngle = lbound
Else
// Right
If MouseAngle > uBound
MouseAngle = uBound
Endif
Endif
// Set the player angle
Bubble_joueur.Angle = MouseAngle
// On mouse button click
If GetRawMouseLeftPressed()
If Bubble_etat_jeu = JEU_READY
Bubble_shoot_bubble()
EndIf
EndIf
EndFunction
// -------
//
// PROGRAMME PRINCIPAL
//
// -------
Bubble_initialiser_jeu()
Bubble_newgame()
do
Bubble_jouer()
Print(ScreenFPS())
Sync()
loop