Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Api's Adventure -puzzlepeli Hollywood-kielellä

jalski [07.11.2010 17:31:09]

#

Yksinkertainen puzzle peli toteutettuna Hollywoodilla, jossa ohjataan Kiinanpalatsikoira Apia ja yritetään kerätä kaikki pelikentällä olevat luut. Tikapuiden avulla pääsee liikkumaan ylä -ja alasuunnassa, kiviä voi työnnellä ja hiekan näköisen peliruudun voi "kaivaa" sivusuunnassa.


Peliprojekti: http://xob.kapsi.fi/~ljl/peli/apisrc.zip

Valmiiksi käännettynä: http://xob.kapsi.fi/~ljl/peli/apiWin32.zip

@APPICON {Ic16x16 = "my16x16icon.png",
	   Ic24x24 = "my24x24icon.png",
	   Ic32x32 = "my32x32icon.png",
	   Ic48x48 = "my48x48icon.png",
	   Ic128x128 = "my128x128icon.png",
	   Ic256x256 = "my256x256icon.png",
	   Ic512x512 = "my512x512icon.png"}



;UI constants
Const #UI_PANEL_HEIGHT = 25
Const #TILESIZE = 49

;Level map dimensions
Const #COLUMNS = 11
Const #ROWS = 8

; Some constanst to help identify map tiles and brushes
Const #EMPTY = 0
Const #WALL = 1
Const #LADDER = 2
Const #WALL2 = 3
Const #ROCK = 4
Const #BONE = 5
Const #PLAYER = 6
Const #LEFT_ARROW_BUTTON = 7
Const #RIGHT_ARROW_BUTTON = 8
Const #SMILEY_BUTTON = 9
Const #APIPLEFT = 10
Const #APIPRIGHT = 11
Const #TITLE = 12
Const #TITLE_TEXT = 13
Const #PRESS_SPACE_TEXT = 14
Const #LEVEL_DONE_TEXT = 15


@DISPLAY {Width = #COLUMNS * #TILESIZE, Height = #ROWS * #TILESIZE + #UI_PANEL_HEIGHT, Title = "Api's Adventure"}

@BRUSH #WALL, "wall.png", {LoadAlpha =  True}
@BRUSH #LADDER, "ladder.png", {LoadAlpha = True}
@BRUSH #WALL2, "wall2.png", {LoadAlpha =  True}
@BRUSH #ROCK, "rock.png", {LoadAlpha =  True}
@BRUSH #BONE, "bone.png", {LoadAlpha =  True}
@BRUSH #PLAYER, "api.png", {LoadAlpha =  True}
@BRUSH #LEFT_ARROW_BUTTON, "left.png", {LoadAlpha =  True}
@BRUSH #RIGHT_ARROW_BUTTON, "right.png", {LoadAlpha =  True}
@BRUSH #SMILEY_BUTTON, "smiley.png", {LoadAlpha =  True}
@BRUSH #APIPLEFT, "apil.png", {LoadAlpha =  True}
@BRUSH #APIPRIGHT, "apir.png", {LoadAlpha =  True}
@BRUSH #TITLE, "title.png"
@BRUSH #TITLE_TEXT, "titlet.png", {LoadAlpha =  True}
@BRUSH #PRESS_SPACE_TEXT, "pspace.png", {LoadAlpha =  True}
@BRUSH #LEVEL_DONE_TEXT, "donet.png", {LoadAlpha =  True}



; Create Brush for empty map tile
CreateBrush(#EMPTY, #TILESIZE, #TILESIZE, #GRAY)



Function DrawUI()
	SetFillStyle(#FILLCOLOR)
	Box(0, 0, 49 * 11, 25, #WHITE)
	DisplayBrush(#LEFT_ARROW_BUTTON, 2, 2)
	DisplayBrush(#RIGHT_ARROW_BUTTON, 22, 2)
	DisplayBrush(#SMILEY_BUTTON, 11 * 47, 2)
	SetFont(#TRUETYPE_DEFAULT, 20)
	SetFontColor(#BLACK)
	TextOut(50, 2, "level: " .. clevel + 1, #BLACK)
EndFunction




; Create level table with methods from the global levels table index n
Function InitLevel(n)

	Local level = {}

	level.map = CopyTable(levels[n].map)

	Function level:DrawMap()
		For Local j = 0 To #ROWS - 1
			For Local i = 0 To #COLUMNS - 1
				DisplayBrush(self.map[i][j], i * #TILESIZE, j * #TILESIZE + #UI_PANEL_HEIGHT)
			Next
		Next
	EndFunction

	level.player = { x = levels[n].player.x, y = levels[n].player.y }

	Function level:DrawPlayer()
		DisplayBrush(#PLAYER, self.player.x * #TILESIZE, self.player.y * #TILESIZE + #UI_PANEL_HEIGHT)
	EndFunction

	Function level:PlayerFall()
		If self.map[self.player.x][self.player.y] <> #EMPTY Then Return

		Local y = self.player.y


		For Local i = y + 1 To #ROWS - 1
			Local found, id, pos = self:SearchObjects(self.player.x, i)

			If self.map[self.player.x][i] <> #EMPTY Or found Then Break

			y = i

		Next

		self.player.y = y

	EndFunction


	level.objects = {}
	level.nobjs = levels[n].nobjs
	level.nbones = levels[n].nbones

	For Local i = 0 To levels[n].nobjs - 1
		level.objects[i] = {id = levels[n].objects[i].id, x = levels[n].objects[i].x, y = levels[n].objects[i].y}
	Next


	Function level:DrawObjects()

		For Local i = 0 To level.nobjs - 1
			DisplayBrush(self.objects[i].id, self.objects[i].x * #TILESIZE, self.objects[i].y * #TILESIZE + #UI_PANEL_HEIGHT)
		Next

	EndFunction


	Function level:SearchObjects(x, y)

		If self.nobjs < 1 Then Return(False, 0, i)

		For Local i = 0 To self.nobjs - 1
			If self.objects[i].x = x And self.objects[i].y = y Then Return(True, self.objects[i].id, i)

		Next

		Return(False, 0, i)

	EndFunction


	Function level:ObjectsFall()

		If self.nobjs < 1 Then Return

		For Local j = 0 To self.nobjs - 1

			Local y = self.objects[j].y


			For Local i = y + 1 To #ROWS - 1
				Local found, id, pos = self:SearchObjects(self.objects[j].x, i)

				If self.map[self.objects[j].x][i] <> #EMPTY Or found Or self.objects[j].x = self.player.x And i = self.player.y Then Break

				y = i

			Next

			self.objects[j].y = y

		Next

	EndFunction


	Function level:SortObjects()
		Sort(self.objects, Function(a, b) Return(a.y > b.y) EndFunction)
	EndFunction


	Function level:Draw()
		self:DrawMap()
		self:DrawObjects()
		self:DrawPlayer()
	EndFunction

	Return(level)


EndFunction




; Level parser, loads levels into global levels table
Function LoadLevels(fid, fname)
	nlevels = 0
	Local Line = 1
	Local x = 0
	Local y = 0
	Local o = 0
	Local b = 0

	levels = {}
	levels[nlevels] = {}
	levels[nlevels].player = {x = 0, y = 0}
	Dim map[11][8]
	levels[nlevels].map = CopyTable(map)
	map = Nil
	levels[nlevels].objects = {}

	OpenFile(fid, fname)

	While  Eof(fid)  = False
		Local c = ReadChr(fid)

		Switch c
			Case ';'
				While  c <> '\n' And Eof(fid) = False Do c = ReadChr(fid)
				Line = Line + 1
			Case '\n':
				y = y + 1

				If x <> 11
					DebugPrint("Level parser error on line:", Line, "column:", x, "Level map must have", #COLUMNS, "columns")
					End
				EndIf

				Line = Line + 1
				x = 0

				If Eof(fid) = False Then c = ReadChr(fid)

				If c = '\n' Or Eof(fid) = True
					If y <> 8
						DebugPrint("Level parser error on line:", Line, "Levels must be separated with one line feed and level map must have:", #ROWS, "rows")
						End
					EndIf

					levels[nlevels].nobjs = o
					levels[nlevels].nbones = b
					nlevels = nlevels + 1
					y = 0
					o = 0
					b = 0
					If Eof(fid) = False
						Line = Line + 1
						levels[nlevels] = {}
						levels[nlevels].player = {x = 0, y = 0}
						Dim map[11][8]
						levels[nlevels].map = CopyTable(map)
						map = Nil
						levels[nlevels].objects = {}
					EndIf
				Else
					Seek(fid, FilePos(fid) - 1)
				EndIf

			Case '0':
				levels[nlevels].map[x][y] = #EMPTY
				x = x + 1
			Case '1':
				levels[nlevels].map[x][y] = #WALL
				x = x + 1
			Case  '2':
				levels[nlevels].map[x][y] = #LADDER
				x = x + 1
			Case '3':
				levels[nlevels].map[x][y] = #WALL2
				x = x + 1
			Case 'b':
				levels[nlevels].objects[o] = {id = #BONE, x = x, y = y}
				b = b + 1
				o = o + 1
				x = x + 1
			Case '@':
				levels[nlevels].player = {x = x, y = y}
				x = x + 1
			Case 'o':
				levels[nlevels].objects[o] = {id = #ROCK, x = x, y = y}
				o = o + 1
				x = x + 1
			Default:
				DebugPrint("Level parser error: impossible character", Chr(c), "on line:", Line, "column:", x)
				End
		EndSwitch

	Wend

EndFunction



Function p_HandlerFunc(msg)

	Switch msg.action
		Case "OnKeyDown":
			Switch msg.key
				Case "UP":
					Local ny = level.player.y - 1
					If ny >= #ROWS Or ny < 0 Then Break

					Local found = level:SearchObjects(level.player.x,  ny)
					If found Then Break;

					If level.map[level.player.x][level.player.y] = #LADDER And level.map[level.player.x][ny] = #LADDER Or
						level.map[level.player.x][level.player.y] = #LADDER And  level.map[level.player.x][ny] = #EMPTY

						level.player.y = ny

						level:PlayerFall()
						level:Draw()
						Flip()
						StartTimer(1)
						WaitTimer(1, 100)

					EndIf

				Case "DOWN":
					Local ny = level.player.y + 1
					If ny >= #ROWS Or ny < 0 Then Break

					Local found = level:SearchObjects(level.player.x,  ny)
					If found Then Break;

					If level.map[level.player.x][ny] = #LADDER Or level.map[level.player.x][level.player.y] = #LADDER And level.map[level.player.x][ny] = #EMPTY

						level.player.y = ny

						level:PlayerFall()
						level:ObjectsFall()
						level:Draw()
						Flip()
						StartTimer(1)
						WaitTimer(1, 100)

					EndIf

				Case "LEFT":
					Local nx = level.player.x - 1
					If nx >= #COLUMNS Or nx < 0 Then Break

					If level.map[nx][level.player.y] <> #WALL
						Local found, id, index = level:SearchObjects(nx, level.player.y)

						If found <> False
							Switch id
								Case #ROCK:
									level:DrawMap()
									level:DrawObjects()
									DisplayBrush(#APIPLEFT, level.player.x * #TILESIZE, level.player.y * #TILESIZE + #UI_PANEL_HEIGHT)
									Flip()
									StartTimer(1)
									WaitTimer(1, 100)

									Local nrx = level.objects[index].x - 1
									If nrx < #COLUMNS And nrx >= 0
										found = level:SearchObjects(nrx, level.player.y)

										If found = False And level.map[nrx][level.player.y] = #EMPTY
											level.objects[index].x = nrx
											level.player.x = nx

											level:SortObjects()
											level:PlayerFall()
											level:ObjectsFall()
											level:Draw()
											Flip()
											Return

										EndIf
									EndIf

								Case #BONE:
									RemoveItem(level.objects, index)
									level.nobjs = level.nobjs - 1
									level.nbones = level.nbones - 1
									level.player.x = nx

							EndSwitch

						Else
							If level.map[nx][level.player.y] = #WALL2 Then level.map[nx][level.player.y] = #EMPTY
							level.player.x = nx
						EndIf

							level:SortObjects()
							level:PlayerFall()
							level:ObjectsFall()
							level:Draw()
							Flip()
							StartTimer(1)
							WaitTimer(1, 100)

					EndIf

				Case "RIGHT":
					Local nx = level.player.x + 1
					If nx >= #COLUMNS Or nx < 0 Then Break

					If level.map[nx][level.player.y] <> #WALL
						Local found, id, index = level:SearchObjects(nx, level.player.y)

						If found <> False
							Switch id
								Case #ROCK:
									level:DrawMap()
									level:DrawObjects()
									DisplayBrush(#APIPRIGHT, level.player.x * #TILESIZE, level.player.y * #TILESIZE + #UI_PANEL_HEIGHT)
									Flip()
									StartTimer(1)
									WaitTimer(1, 100)

									Local nrx = level.objects[index].x + 1
									If nrx < #COLUMNS And nrx >= 0
										found = level:SearchObjects(nrx, level.player.y)

										If found = False And level.map[nrx][level.player.y] = #EMPTY
											level.objects[index].x = nrx
											level.player.x = nx

											level:SortObjects()
											level:PlayerFall()
											level:ObjectsFall()
											level:Draw()
											Flip()
											Return

										EndIf
									EndIf

								Case #BONE:
									RemoveItem(level.objects, index)
									level.nobjs = level.nobjs - 1
									level.nbones = level.nbones - 1
									level.player.x = nx

							EndSwitch
						Else
							If level.map[nx][level.player.y] = #WALL2 Then level.map[nx][level.player.y] = #EMPTY
							level.player.x = nx
						EndIf

							level:SortObjects()
							level:PlayerFall()
							level:ObjectsFall()
							level:Draw()
							Flip()
							StartTimer(1)
							WaitTimer(1, 100)

					EndIf

			EndSwitch

	EndSwitch

	If level.nbones < 1
		clevel = clevel + 1
		clevel = Wrap(clevel, 0, nlevels)
		level = InitLevel(clevel)
		DisplayBrush(#LEVEL_DONE_TEXT, #CENTER, #CENTER)
		Flip()
		StartTimer(1)
		WaitTimer(1, 1000)
		DrawUI()
		level:SortObjects()
		level:PlayerFall()
		level:ObjectsFall()
		level:Draw()
		Flip()
	EndIf

EndFunction





Function p_ButtonHandler(msg)

	Switch msg.action
		Case "OnMouseUp":
			Switch msg.id
				Case 1:
					clevel = clevel - 1
					clevel = Wrap(clevel, 0, nlevels)
					level = InitLevel(clevel)
					DrawUI()
					level:SortObjects()
					level:PlayerFall()
					level:ObjectsFall()
					level:Draw()
					Flip()
				Case 2:
					clevel = clevel + 1
					clevel = Wrap(clevel, 0, nlevels)
					level = InitLevel(clevel)
					DrawUI()
					level:SortObjects()
					level:PlayerFall()
					level:ObjectsFall()
					level:Draw()
					Flip()
				Case 3:
					level = InitLevel(clevel)
					DrawUI()
					level:SortObjects()
					level:PlayerFall()
					level:ObjectsFall()
					level:Draw()
					Flip()

			EndSwitch

		Case "OnMouseOver":
		; Nothing yet, but maybe one could darken UI buttons to highlight them.
	EndSwitch

EndFunction


evtmatch = {OnMouseUp = p_ButtonHandler, OnMouseOver = p_ButtonHandler}
MakeButton(1, #SIMPLEBUTTON, 2, 2, 20, 20, evtmatch)
MakeButton(2, #SIMPLEBUTTON, 22, 2, 20, 20, evtmatch)
MakeButton(3, #SIMPLEBUTTON, 11 * 47, 2, 20, 20, evtmatch)


LoadLevels(1, "levels.txt")

; Current level
clevel = 0
level = InitLevel(clevel)

DisplayBrush(#TITLE, #CENTER, #CENTER)
DisplayBrushFX(#TITLE_TEXT,#CENTER, #CENTER, {Type = #ZOOMCENTER})
DisplayBrushFX(#PRESS_SPACE_TEXT, #CENTER, #BOTTOM, {Type = #VSTRETCHCENTER})
WaitKeyDown("SPACE")

BeginDoubleBuffer()

level:SortObjects()
DrawUI()
level:Draw()
Flip()

InstallEventHandler({OnKeyDown = p_HandlerFunc})
SetEventTimeout(50)


Repeat
	WaitEvent
Forever

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta