Post your minigame

BlitzMax Forums/BlitzMax Programming/Post your minigame

nawi(Posted 2008) [#1]
Here's a thread for any minigame you've created. A good place to test your game idea too.

I'll start with my game, where you control two players at once. Since they start at different directions, they will always travel in different direction! You must reach both white tiles at the same time to complete the game.



SuperStrict
AppTitle = "Small game"
Const GfxWidth:Int = 640,GfxHeight:Int = 480
Graphics GfxWidth,GfxHeight,0

Const Radius:Int = 32

Type Player
	Field X:Float,Y:Float,Angle:Float
	Global PlayerList:TList
	Method New()
		ListAddLast(PlayerList,Self)
	End Method

	Function TurnLeft()
		For Local P:Player = EachIn Player.PlayerList
			P.Angle:-5
		Next
	End Function

	Function TurnRight()
		For Local P:Player = EachIn Player.PlayerList
			P.Angle:+5
		Next
	End Function

	Function Forward()
		For Local P:Player = EachIn Player.PlayerList
			P.X:+Cos(P.Angle)
			P.Y:+Sin(P.Angle)
		Next
	End Function

Function Backward()
		For Local P:Player = EachIn Player.PlayerList
			P.X:-Cos(P.Angle)
			P.Y:-Sin(P.Angle)
		Next
	End Function

	Function Draw()
		For Local P:Player = EachIn Player.PlayerList
			SetColor 128,128,255
			DrawOval P.X-Radius*0.5,P.Y-Radius*0.5,Radius,Radius
			SetColor 255,255,255
			DrawLine P.X,P.Y,P.X+Cos(P.Angle)*Radius*0.5,P.Y+Sin(P.Angle)*Radius*0.5,0
		Next
	End Function
End Type
Player.PlayerList = CreateList()

Local Map:Int[GfxWidth/Radius,GfxHeight/Radius]
SetClsColor 0,0,0

Map[4,4] = 1; Map[4,5] = 1; Map[4,6] = 1; Map[9,9] = 1; Map[10,9] = 1; Map[11,9] = 1
Map[5,6] = 1; Map[6,6] = 1; Map[7,6] = 1; Map[11,8] = 1; Map[11,7] = 1; Map[11,6] = 1
Map[8,6] = 1; Map[9,6] = 1; Map[10,6] = 1; Map[11,5] = 1; Map[11,4] = 1; Map[11,3] =1;
Map[11,2] = 1; Map[12,2] = 1; Map[13,2] = 1; Map[14,2] = 1; Map[15,2] = 1; Map[16,2] = 1
Map[11,10] = 1; Map[11,11] = 1; Map[16,1] = 1; Map[16,0] = 2; Map[12,11] = 1; Map[13,11] = 2
Map[5,4] = 1; Map[6,4] = 1; Map[7,4] = 1; Map[8,4] = 1; Map[9,4] = 1; Map[10,4] = 1;
Map[3,4] = 1; Map[2,4] = 1; Map[1,4] = 1; Map[0,4] = 1; Map[4,3] = 1; Map[4,2] = 1
Map[5,2] = 1; Map[6,2] = 1; Map[7,2] = 1; Map[8,2] = 1; Map[9,2] = 1; Map[10,2] = 1
Map[8,9] = 1; Map[7,9] = 1; Map[6,9] = 1; Map[5,9] = 1; Map[4,9] = 1; Map[3,9] = 1; Map[2,9] = 1
Map[1,9] = 1; Map[0,9] = 1; Map[0,8] = 1; Map[0,7] = 1; Map[0,6] = 1; Map[0,5] = 1; Map[7,8] = 1
Map[7,7] = 1; Map[12,9] = 1; Map[13,9] = 1; Map[14,9] = 1; Map[14,10] = 1; Map[14,11] = 1
Map[12,6] = 1; Map[13,6] = 1; Map[14,6] = 1; Map[15,6] = 1; Map[16,6] = 1; Map[16,5] = 1;
Map[16,4] = 1; Map[16,3] = 1; Map[14,1] = 1; Map[14,0] = 1; Map[15,0] = 1; Map[11,0] = 1
Map[11,1] = 1; Map[12,0] = 1; Map[13,0] = 1; Map[14,8] = 1; Map[14,7] = 1

Local p1:Player = New Player
p1.X = 304; p1.Y = 304; p1.Angle = 180
Local p2:Player = New Player
p2.X = 144; p2.Y = 144; p2.Angle = 270

Repeat
	If KeyDown(KEY_LEFT) Then Player.TurnLeft()
	If KeyDown(KEY_RIGHT) Then Player.TurnRight()
	If KeyDown(KEY_UP) Then Player.Forward()
	If KeyDown(KEY_DOWN) Then Player.Backward()

	Local Reset:Int = 0
	For Local P:Player = EachIn Player.PlayerList
		If Map[Floor(P.X/Radius),Floor(P.Y/Radius)] = 0 Then
			Reset = 1
			Exit
		EndIf
	Next
	If Reset = 1 Then
		p1.X = 304; p1.Y = 304; p1.Angle = 180
		p2.X = 144; p2.Y = 144; p2.Angle = 270
	EndIf

	DrawMap(Map)
	Player.Draw()

	If Map[Floor(p1.X/Radius),Floor(p1.Y/Radius)] = 2 And Map[Floor(p2.X/Radius),Floor(p2.Y/Radius)] = 2 Then
		SetColor 255,255,255
		DrawText "GAME COMPLETE",GfxWidth*0.5-TextWidth("GAME COMPLETE")*0.5,GfxHeight*0.5
		Flip
		Repeat
		Until KeyHit(KEY_ESCAPE)
		End
	EndIf

	Flip
	Cls

Until KeyHit(KEY_ESCAPE)

Function DrawMap(Map:Int[,])
	For Local x:Int = 0 To GfxWidth/Radius-1
		For Local y:Int = 0 To GfxHeight/Radius-1
			If Map[x,y] = 1 Then
				SetColor(128,128,128)
				DrawRect x*Radius,y*Radius,Radius,Radius
			ElseIf Map[x,y] = 2 Then
				SetColor(255,255,255)
				DrawRect  x*Radius,y*Radius,Radius,Radius
			EndIf
		Next
	Next
End Function



Trader3564(Posted 2008) [#2]
*CTRL+C**CTRL+V**F5*


Trader3564(Posted 2008) [#3]
Thats just a cool idea! Really well done.


Czar Flavius(Posted 2008) [#4]
Cool game, but try making them turn at 90 degree angles. It will be easier.


nawi(Posted 2008) [#5]
Here's my next minigame: defense. The difference to most tower defense games is that you need to actually aim the towers with your mouse.

How to play:
-Mouse button 2 enables shooting
-Mouse button 1 creates towers



SuperStrict
AppTitle = "Defense"
Const GfxWidth:Int = 640,GfxHeight:Int = 480
Graphics GfxWidth,GfxHeight,0

Const Grid:Int=32
Const MapWidth:Int=GfxWidth/Grid-3
Const MapHeight:Int=GfxHeight/Grid-2
Const EnemySize:Int = Grid*0.6

Global Gold:Int=5,Shooting:Int=0
Global Map:Int[MapWidth,MapHeight]
Global MX:Int,MY:Int
Global Level:Int=0,StartTime:Int,SpawnCount:Int,SpawnTimer:Int,Score:Int,Lives:Int=10,STimer:Int
Global MouseMode:Int=0,SelectedTower:Tower
'0 = nothing
'1 = selected tower

For Local y:Int = 0 To MapHeight-1 Step 2
	For Local x:Int = 0 To MapWidth-1
		Map[x,y] = 1
	Next
Next
For Local y:Int = 0 To MapHeight-1 Step 4
	Map[0,y] = 0
Next
For Local y:Int = 2 To MapHeight-1 Step 4
	Map[MapWidth-1,y] = 0
Next
Map[0,0] = 3
Map[0,MapHeight-1] = 2
Type Tower
	Field X:Int,Y:Int
	Field Damage:Int
	Field Rate:Int
	Field Level:Int
	Field Angle:Int
	Field ShootingTimer:Int
	Global List:TList

	Method New()
		Level = 1
		Damage = 1
		Rate = 800
		ShootingTimer = MilliSecs()
		ListAddLast(Tower.List,Self)
	End Method

	Function Shoot()
		For Local T:Tower = EachIn Tower.List
			If MilliSecs()-T.ShootingTimer>T.Rate Then
				T.ShootingTimer = MilliSecs()
				If Shooting
					Local A:Arrow = New Arrow
					A.X = T.X+Grid*0.5
					A.Y = T.Y+Grid*0.5
					A.Angle = T.Angle+Rand(-4,4)
					A.Damage = T.Damage
				EndIf
			EndIf
		Next
	End Function
	Function Draw()
		Local DrawColor:Int
		For Local T:Tower = EachIn Tower.List
			'Update angle
			If Shooting Then
				T.Angle = ATan2(MY-(T.Y+Grid*0.5),MX-(T.X+Grid*0.5))
			EndIf
			DrawColor = 128+T.Level
			If DrawColor>255 Then DrawColor = 255
			SetColor DrawColor,30,30
			DrawLine T.X+Grid*0.5+Cos(T.Angle)*Grid*0.3,T.Y+Grid*0.5+Sin(T.Angle)*Grid*0.3,T.X+Grid*0.5,T.Y+Grid*0.5
			SetScale(0.7,0.7)
			SetColor(255,255,255)
			DrawText T.Level,T.X+Grid-TextWidth(T.Level),T.Y+Grid-11
			SetScale(1,1)
		Next
	End Function

	Function NotFound:Int(x:Int,y:Int)
		For Local T:Tower = EachIn Tower.List
			If Floor(x/Grid) = T.X/Grid And Floor(y/Grid) = T.Y/Grid Then Return False
		Next
		Return True
	End Function

	Function GetTower:Tower(x:Int,y:Int)
		For Local T:Tower = EachIn Tower.List
			If Floor(x/Grid) = T.X/Grid And Floor(y/Grid) = T.Y/Grid Then Return T
		Next
		Return Null
	End Function
End Type
Tower.List = CreateList()

Type Arrow
	Field X:Float,Y:Float,Angle:Float
	Field Damage:Int
	Global List:TList

	Method New()
		ListAddLast(List,Self)
	End Method

	Function Update()
		For Local A:Arrow = EachIn Arrow.List
			A.X = A.X + Cos(A.Angle)*2.0
			A.Y = A.Y + Sin(A.Angle)*2.0
			If A.X < 0 Or A.Y < 0 Or A.X > MapWidth*Grid Or A.Y > MapHeight*Grid Then
				ListRemove(List,A)
			Else
				For Local E:Enemy = EachIn Enemy.List
					If Distance(A.X,A.Y,E.X,E.Y) < EnemySize*0.5 Then
						E.HP = E.HP - A.Damage
						If E.HP < 0 Then
							ListRemove(Enemy.List,E)
							Score = Score+E.MaxHP/10
							Gold = Gold + Level
						EndIf
						ListRemove(List,A)
						Exit
					EndIf
				Next
			EndIf
		Next
	End Function

	Function Draw()
		SetColor 128,128,255
		For Local A:Arrow = EachIn Arrow.List
			DrawLine A.X,A.Y,A.X-Cos(A.Angle)*5,A.Y-Sin(A.Angle)*5
		Next
	End Function
End Type
Arrow.List = CreateList()

Type Enemy
	Field HP:Int,MaxHP:Int
	Field X:Int,Y:Int
	Global List:TList

	Function Draw()
		For Local E:Enemy = EachIn Enemy.List
			If (Floor((E.Y)/Grid)+3) Mod 4 = 0 And E.Y>=Grid*1.5 And E.X < (MapWidth-0.5)*Grid Then E.X = E.X + 1
			If (Floor((E.Y)/Grid)+1) Mod 4 = 0 And E.Y>=Grid*1.5 And E.X > Grid*0.5 Then E.X = E.X - 1
			If Map[Floor(E.X/Grid),Floor((E.Y+Grid*0.5)/Grid)] <> 1  Then E.Y = E.Y+1
			SetColor Float(E.HP)/Float(E.MaxHP)*255.0,Float(E.HP)/Float(E.MaxHP)*255.0,Float(E.HP)/Float(E.MaxHP)*255.0
			DrawOval E.X-EnemySize*0.5,E.Y-EnemySize*0.5,EnemySize,EnemySize
			Local FX:Int = Floor(E.X/Grid),FY:Int = Floor(E.Y/Grid)
			If FX>=0 And FY=>0 And FX<MapWidth And FY<MapHeight Then
				If Map[FX,FY] = 2 Then
					Lives = Lives - 1
					If Lives = 0 Then RuntimeError "Game over!"
					ListRemove(Enemy.List,E)
				EndIf
			EndIf
		Next
	End Function

	Method New()
		ListAddLast(List,Self)
	End Method
End Type
Enemy.List = CreateList()

StartTime = MilliSecs()

Repeat
	If MilliSecs()>SpawnTimer+45000 Then
		SpawnTimer = MilliSecs()
		SpawnCount = SpawnCount + 60
		Level = Level + 1
	EndIf
	If SpawnCount>0 And MilliSecs()>STimer+400 Then
		STimer = MilliSecs()
		SpawnCount = SpawnCount - 1
		Local E:Enemy = New enemy
		E.X = Grid*0.5
		E.Y = 0
		E.HP = Level * Level * Level
		E.MaxHP = Level * Level * Level
		If E.HP <= 0 Then E.HP = 1
		If E.MaxHP <= 0 Then E.MaxHP = 1
	EndIf


	MX = MouseX()
	MY = MouseY()
	If MouseHit(2) Then Shooting=1-Shooting

	If MouseHit(1) Then
		If MouseMode = 0 Then
			If Floor(MX/Grid) >= 0 And Floor(MY/Grid) >= 0 And Floor(MX/Grid) < MapWidth And Floor(MY/Grid) < MapHeight And Tower.NotFound(MX,MY) Then
				If Map[Floor(MX/Grid),Floor(MY/Grid)] = 1 And Gold>=2 Then
					Gold = Gold - 2
					Local T:Tower = New Tower
					T.X = Floor(MX/Grid)*Grid
					T.Y = Floor(MY/Grid)*Grid
				EndIf
			ElseIf Tower.NotFound(MX,MY) = False Then
				Local T:Tower = Tower.GetTower(MX,MY)
				MouseMode = 1
				SelectedTower:Tower = T
			EndIf
		ElseIf MouseMode = 1 Then
			If MX>=MapWidth*Grid+5 And MY>=190 And MX<MapWidth*Grid+5+TextWidth("Upgrade for") And MY<190+TextHeight("!")*2 Then
					If Gold>=SelectedTower.Level*SelectedTower.Level Then
					Gold=Gold-SelectedTower.Level*SelectedTower.Level
					SelectedTower.Level = SelectedTower.Level+1
					SelectedTower.Rate = SelectedTower.Rate*0.98
					If SelectedTower.Rate<200 Then SelectedTower.Rate = 200
					SelectedTower.Damage = (SelectedTower.Damage+1)*1.25
				EndIf
			Else
				MouseMode = 0
				SelectedTower = Null
			EndIf
		EndIf
	EndIf
	Tower.Shoot()
	Arrow.Update()

	DrawMap()
	Tower.Draw()
	Enemy.Draw()
	Arrow.Draw()
	SetColor 255,255,0
	DrawText "Gold: "+Gold,MapWidth*Grid+5,5
	SetColor 128,255,128
	DrawText "Level: "+Level,MapWidth*Grid+5,20
	SetColor 255,128,128
	DrawText "Score: "+Score,MapWidth*Grid+5,35
	SetColor 128,128,255
	DrawText "Time: "+((MilliSecs()-StartTime)/1000),MapWidth*Grid+5,50
	SetColor 255,255,255
	DrawText "Lives: "+Lives,MapWidth*Grid+5,65
	SetScale(0.9,1)
	DrawText ((SpawnTimer+45000-MilliSecs())/1000)+"s to spawn",MapWidth*Grid+5,80
	SetScale(1,1)


	If MouseMode = 1 And SelectedTower <> Null Then
		DrawText "Tower:",MapWidth*Grid+5,130
		DrawText "Level "+SelectedTower.Level,MapWidth*Grid+5,145
		DrawText "Dmg "+SelectedTower.Damage,MapWidth*Grid+5,160
		DrawText "Rate "+SelectedTower.Rate,MapWidth*Grid+5,175
		DrawRect MapWidth*Grid+5,190,TextWidth("Upgrade for"),TextHeight("!")*2
		SetColor 0,0,0
		DrawText "Upgrade for",MapWidth*Grid+5,190
		DrawText SelectedTower.Level*SelectedTower.Level+"g",MapWidth*Grid+5,205
	EndIf

	Flip
	Cls

	If KeyHit(KEY_P) Then
		Repeat
		Until KeyHit(KEY_P)
	EndIf
Until KeyHit(KEY_ESCAPE)

Function DrawMap()
	SetColor 255,255,255
	DrawLine MapWidth*Grid,0,MapWidth*Grid,MapHeight*Grid,0
	DrawLine 0,MapHeight*Grid,MapWidth*Grid,MapHeight*Grid,0
	For Local x:Int = 0 To MapWidth-1
		For Local y:Int = 0 To MapHeight-1
			If Map[x,y] = 0 Then
				SetColor 0,0,0
			ElseIf Map[x,y] = 1
				SetColor 255,255,255
			ElseIf Map[x,y] = 2
				SetColor 255,0,0
			ElseIf Map[x,y] = 3
				SetColor 0,255,0
			EndIf
			DrawRect x*Grid,y*Grid,Grid,Grid
			SetColor 0,0,0
			DrawRect x*Grid+1,y*Grid+1,Grid-2,Grid-2
		Next
	Next
End Function

Function Distance:Float(x1:Int,y1:Int,x2:Int,y2:Int)
	x1 = x1-x2
	y1 = y1-y2
	Return Sqr(x1*x1+y1*y1)
End Function




Zeke(Posted 2008) [#6]
wow. cool minigame. :D i like


Twitchfactor(Posted 2008) [#7]
I like the mini-game idea. Unfortunately, the Defense game doesn't seem to work properly. I can place 2 towers, make them shoot and that's it. No enemies ever spawn.

I still like the idea of rapid-prototyping or minigames, though.


nawi(Posted 2008) [#8]
Do you have a ridiculously high uptime so that Millisecs() returns negative numbers? I can't figure out any other reason for that bug.


Twitchfactor(Posted 2008) [#9]
Yeah, just checked millisecs() time at the start of the game and it's somethin like -1560744888.

BTW, the other game's cool, even though my expectation was that I would slide along the walls and not go through them.

How long did it take you to write these?


nawi(Posted 2008) [#10]
Not that long.