Help with Tile-Based Game

Blitz3D Forums/Blitz3D Programming/Help with Tile-Based Game

This project is not 3D (it's 2D), but it's not B+ or BMax either, so I just put it in here. I'm making a tile-based game, but I'm having a hard time making it tiled. Basically, I want to position 20 square images in 20 random spots, but they fit in the tiles. The default tile will be a brownish color, but every tile you walk over will become a lighter browish color. Basically I need to know how to position the 20 random images IN the tiles, and not slightly out of.

This is my current "loading" code:
Function LoadLevel()
	
	For i = 1 To 20
		newRock.mineral = New mineral
		newRock\image = CreateImage(20, 20)
		newRock\x# = Rand(0,800)
		newRock\y# = Rand(0,600)
		v = Rand(0, 22)
		If v < 7
			newRock\value = 25
		ElseIf v > 6 And v > 13
			newRock\value = 50
		ElseIf v > 13 And v < 17
			newRock\value = 100
		ElseIf v > 16 And v > 20
			newRock\value = 250
		ElseIf v = 20 Or v = 21
			newRock\value = 500
		ElseIf v = 22
			newRock\value = 1000
		EndIf
		
		newRock\points = (newRock\value * 10) / 2
		
		SetBuffer ImageBuffer(newRock\image)
		
		If newRock\value = 25
			Color 0, 30, 0
		ElseIf newRock\value = 50
			Color 0, 75, 0
		ElseIf newRock\value = 100
			Color 0, 130, 0
		ElseIf newRock\value = 250
			Color 0, 185, 0
		ElseIf newRock\value = 500
			Color 0, 215, 0
		ElseIf newRock\value = 1000
			Color 0, 255, 0
		EndIf
		
		Rect 0, 0, 20, 20
		
		SetBuffer BackBuffer()
		
	Next
	
	
End Function

Each of the "tiles" is 40x40. I'm also having trouble with map scrolling.

My questions:
1) How to make the 20 random 40x40 images fit into the 40x40 tiles.
2) How to integrate map scrolling.

Thanks for any help!

Any takers?

Personally, I think your loader has some problems. Instead of all those If...ElseIf...ElseIf... constructs I would recommend something like data statements or an array.

You have some 'bugs' in the code as shown above...
                ElseIf v > 6 And v > 13            ; v>6 is pointless here
			newRock\value = 50
		ElseIf v > 13 And v < 17
			newRock\value = 100
		ElseIf v > 16 And v > 20            ; v>16 is pointless here
			newRock\value = 250



I would recommend the use of Select..Case

Select newrock\value
             Case 25
                  Color 0, 30, 0
             Case 50
                  Color 0, 75, 0
             Case 100
                  Color 0, 130, 0
             Case 250
                  Color 0, 185, 0
             Case 500
                  Color 0, 215, 0
             Case 1000
                  Color 0, 255, 0
End Select


[edit]
... and to answer your problem... I think you want to use
newRock\x# = Rand(0,20)*40
newRock\y# = Rand(0,15)*40

to align the placed rocks with a 40x40 grid

OK, thanks.

Any ideas on how to make it "scroll?"

Nevermind. It's "scrolling" now.

OK. I'm having more trouble.

Here is the code:
;..::DRILLER::..
;by Steven Campbell @ No Enemies Development
;steven@...
;Special Thanks: Sam Schoenholz

Graphics 800,600,16,2
SetBuffer BackBuffer()
AutoMidHandle False
SeedRnd MilliSecs()

;..::TYPES::..
;mineral type
Type mineral
	Field value
	Field points
	Field x, y
	Field image
	Field min_depth
	Field max_depth
	Field frame
End Type
;building type
Type building
	Field image
	Field name$
	Field x, y
End Type
;upgrade type
Type upgrade
	Field name$
	Field u_type$
	Field image
	Field index
End Type 

;..::GLOBALS::..
;main globals
Global logic$ = "game"
Global page = 0
;statistics
Global mineral_num
Global mineral_got
Global score, money, fuel, HP
Global PlayerX = 10
Global PlayerY = 10
;images
Global digger = LoadImage("images\digger.bmp")
Global tile_dirt = LoadAnimImage("images\dirt.bmp", 40, 40, 0, 2)
Global minerals  = LoadAnimImage("images\tiles.bmp", 40, 40, 0, 8)
;time
Global fueltime, fueltime2
;scrolling
Global OffsetX = 0
Global NewOffsetX = 0
Global OffsetY = 0
Global NewOffsetY = 0

;..::ARRAYS::..
;map
Dim map(2,0,0)

;..::CONSTANTS::..
;key consts.
Const KEY_UP     = 208
Const KEY_DOWN   = 200
Const KEY_LEFT   = 203
Const KEY_RIGHT  = 205
Const KEY_SPACE  = 57
Const KEY_ENTER  = 28
Const KEY_ESC    = 1

BuildLevel()

;..::MAIN LOOP::..
While Not KeyDown(KEY_ESC)
	UpdateLogic()
Wend

;..::]] FUNCTIONS [[::..

;MAIN FUNCTIONS

;UpdateLogic() - updates the game
Function UpdateLogic()
	
	Select logic$
		
		Case "game"
			
			UpdateGame()
		
		Case "menu"
			
			UpdateMenu()
		
		Case "ingame"
			
			;update ingame menu
		
		Case "credits"
			
			;update credits
		
		Case "intro"
			
			;update intro
		
		Case "fuelstation"
			
			;update fuel station
		
		Case "upgradeshop"
			
			;update upgrade shop
		
		Case "repairshop"
			
			;update repair shop
		
		Case "deposit"
			
			;update mineral deposit
		
	End Select
	
End Function

;BuildLevel() - creates the level
Function BuildLevel()
	
	For i = 1 To 20
		
		newMineral.mineral = New mineral
		newMineral\image = CopyImage(minerals)
		
		v = Rand(0, 8)
		
		If v = 1
			newMineral\value = 50
			newMineral\min_depth = 0
			newMineral\max_depth = 2000
			newMineral\frame = 0
		ElseIf v = 2
			newMineral\value = 100
			newMineral\min_depth = 10
			newMineral\max_depth = 2000
			newMineral\frame = 1
		ElseIf v = 3
			newMineral\value = 250
			newMineral\min_depth = 50
			newMineral\max_depth = 2000
			newMineral\frame = 2
		ElseIf v = 4
			newMineral\value = 500
			newMineral\min_depth = 100
			newMineral\max_depth = 2000
			newMineral\frame = 3
		ElseIf v = 5
			newMineral\value = 1000
			newMineral\min_depth = 500
			newMineral\max_depth = 2000
			newMineral\frame = 4
		ElseIf v = 6
			newMineral\value = 5000
			newMineral\min_depth = 750
			newMineral\max_depth = 2000
			newMineral\frame = 5
		ElseIf v = 7
			newMineral\value = 20000
			newMineral\min_depth = 1000
			newMineral\max_depth = 2000
			newMineral\frame = 6
		ElseIf v = 8
			newMineral\value = 100000
			newMineral\min_depth = 1750
			newMineral\max_depth = 2000
			newMineral\frame = 7
		EndIf 
			
		
		newMineral\x = Rand(-20, 20)*40
		newMineral\y = Rand(newMineral\min_depth, newMineral\max_depth)*40
	
	Next 
	
End Function 	

;GAME FUNCTIONS

;UpdateGame() - main updating function
Function UpdateGame()
	
	UpdateScrolling()
	UpdateMinerals()
	DrawLevel()
	UpdateMovement()
	
	Flip
	Cls
	
End Function 

;UpdateScrolling() - update the map scrolling
Function UpdateScrolling()

	If PlayerX>OffsetX+760 Then NewOffsetX = NewOffsetX + 100
	If PlayerX<OffsetX+40 And OffsetX > 0 Then NewOffsetX = NewOffsetX - 100
		While NewOffsetX-OffsetX>0
			Cls
			OffsetX = OffsetX + 2
			Origin -OffsetX,0
			DrawImage digger,PlayerX,PlayerY
			Flip 
		Wend
		;Preform Tweening
		While NewOffsetX-OffsetX<0 
			Cls 
			OffsetX = OffsetX - 2
			Origin -OffsetX,0
			DrawImage digger,PlayerX,PlayerY
			Flip
		Wend
	
	If PlayerY>OffsetY+560 Then NewOffsetY = NewOffsetY + 100
	If PlayerY<OffsetY+40 And OffsetY > 0 Then NewOffsetY = NewOffsetY - 100
		While NewOffsetY-OffsetY>0
			Cls
			OffsetY = OffsetY + 2
			Origin -OffsetY,0
			DrawImage digger,PlayerX,PlayerY,PlayerAnimation
			Flip
		Wend
		;Preform Tweening
		While NewOffsetY-OffsetY<0 
			Cls 
			OffsetY = OffsetY - 2
			Origin -OffsetY,0
			DrawImage digger,PlayerX,PlayerY,PlayerAnimation
			Flip
		Wend


End Function

;UpdateMovement() - update player movement
Function UpdateMovement()
	
	If KeyHit(KEY_LEFT)
		PlayerX = PlayerX - 40
	EndIf
	
	If KeyHit(KEY_RIGHT)
		PlayerX = PlayerX + 40
	EndIf
	
	If KeyHit(KEY_UP)
		PlayerY = PlayerY - 40
	EndIf
	
	If KeyHit(KEY_DOWN)
		PlayerY = PlayerY + 40
	EndIf
	
End Function

;UpdateMinerals() - updates all the minerals
Function UpdateMinerals()
	
	mineral_num = 0
	
	For u.mineral = Each mineral
		
		mineral_num = 0
		
		If ImagesCollide(digger, PlayerX, PlayerY, 0, u\image, u\x, u\y, u\frame)
			score = score + u\points
			money = money + u\value
			mineral_got = mineral_got + 1
			FreeImage u\image
			Delete u
		EndIf
		
	Next

End Function  

;DrawLevel() - draws the current level
Function DrawLevel()

	For x = 0 To 40*40
		For y = 0 To 2000
		
			DrawImage tile_dirt, x, y, 0
			
		Next
	Next
	
	For m.mineral = Each mineral
		
		DrawImage m\image, m\x, m\y, m\frame
		
	Next 	

End Function

;MENU FUNCTIONS

;UpdateMenu() - updates the main menu
Function UpdateMenu()
	
	Text 400,300, "PRESS [SPACE] TO START",1,1
	Text 400,320, "PRESS [ESC] TO EXIT",1,1
	
	If KeyHit(57)
		BuildLevel()
		logic$ = "game"
	EndIf 
	
	Flip
	Cls
	
End Function

For some reason, when I run it, it won't draw all of the map. What is supposed to happen is that the entire screen is covered with a brownish-color, and that there are scattered circles on it. And there is also supposed to be a yellow smiley face, controlled by the arrow keys. For some reason, when you run it, you get a blank screen.

Any ideas on how to draw the level? Or suggestions on how to get started?

PS: You can just replace the images if you want.

A rogue Cls somewhere, I'm guessing. You seem to have loads of them dotted around in your code, for some reason.

Well, I deleted all the Cls's and the problem still remains. I don't know what could be causing all this, except for maybe the map was drawn off-screen. But yes, a rogue Cls would probably be the most logical explaination.

TBH, after another quick look you seem to be doing some pretty strange things in that code. For example:

BuildMesh()
- Any reason you're using CopyImage for each new mineral?
- Your if/else block doesn't cater for when Rand returns 0
- You're setting the x/y coords to some potentially huge numbers e.g. Rand(newMineral\min_depth, newMineral\max_depth)*40

DrawLevel()
	For x = 0 To 40*40
		For y = 0 To 2000
		
			DrawImage tile_dirt, x, y, 0
			
		Next
	Next

You're drawing tile_dirt THOUSANDS of times, at only a pixel apart. Are you missing Step in those For/Next loops, by any chance?

OK. I fixed all those, yet I still see a black screen. I tested it on another computer, and it worked fine there...I think it's a gfx card issue, so I'm trying to use nSprite to make it 3D.

OK. I've got it working now. Thanks for all your help!