Hi everyone!
This is my first post here, and the interface is kind of confusing, so I’m sorry if this is formatted strangely. I’ve been trying to teach myself how to code through this game. It’s a tile sliding game, trying to order the tiles into a correct position. Currently, I’m just trying to get movement to work, and the sprites and abilit to start/end/win a game haven’t been implemented. I’ve gotten most of it going, but I can’t seem to get the tiles to move around correctly.
I want one of three things to happen: if the tile tries to move past the boundaries, it can’t move; if the tile tries to move onto another tile, it can’t move; if the tile tries to move to a free space, it moves. I’ve been trying to do this using a for loop (as the names of the tiles are stored under the same variable name, so I have to access them in a way other than by name). However, I can’t get the code to do those three things consistently. I’m pretty sure the problem is with the for loop and if statement combination I have, but I can’t think of another method for doing this.
Sorry that some of the comments haven’t been updated as I’ve been changing the code, but most of it is still correct.
I’m using an iPad Pro, version 11.2.2, and Pythonista version 3.2.
Any help would be appreciated. Code starts after this line.
'''Description: A 4x4 board of numbered tiles has one missing space and is randomly set up. To win the game, the player must slide tiles over to put the tiles back in order.
Variants: Instead of numbers, you can have a scrambled picture cut up into 4x4 tiles.'''
from scene import *
import random
import ui
import marshal
import string
import sound
import math
import time
import Image, ImageDraw
class Game(Scene):
MARGIN_OF_ERROR = 33
#Creates background and initial variables that the rest of the game builds off of.
def setup(self):
self.background_color = '#646464'
self.create_tile()
self.drag = False
self.Tile = None
self.touch_location = None
self.touched_tile = None
#Creates tiles and adds their graphics by randomly selecting a position (was supposed to have numbers but couldn't get that working), adds that position to actual_position list and removes it from position_options lists so no tile is put in the same spot. It then adds all those tiles the game generated into a list that gets accessed later in the game.
def create_tile(self):
position_options = [(522, 510), (522, 444), (522, 378), (522, 312), (588, 510), (588, 444), (588, 378),
(588, 312), (654, 510), (654, 444), (654, 378), (654, 312), (456, 510), (456, 444),
(456, 378)] #possible positions
actual_position = []
self.tiles = []
t_shape = 'plf:Tile_BoxCrate' #sprite of tile
for j in range(15):
position = random.choice(position_options) #chooses position
actual_position.append(position) #adds position to other list
position_options.remove(position) #removes position so it can't be rechosen
self.Tile = SpriteNode(t_shape, position) #creates tile
self.tiles.append(self.Tile) #adds that tile to self.tiles list
self.add_child(self.Tile) #adds tile to gameboard
#this function determines where player has touched. It goes through every position option and compares the x and y value of where player touched to intial position option with a margin of error of twenty. It then adds that position to a self.drag variable to be used elsewhere in the class.
def touch_began(self, touch):
position_options = [(522, 510), (522, 444), (522, 378), (522, 312), (588, 510), (588, 444), (588, 378),
(588, 312), (654, 510), (654, 444), (654, 378), (654, 312), (456, 510), (456, 444),
(456, 378), (456, 312)]
for j in position_options:
if touch.location[0] <= j[0] + self.MARGIN_OF_ERROR and touch.location[0] >= j[0] - self.MARGIN_OF_ERROR and touch.location[1] <= j[1] + self.MARGIN_OF_ERROR and touch.location[1] >= j[1] - self.MARGIN_OF_ERROR:
#checks if touch.location is within the margin of error to a position option
self.drag = j #sets empty variable self.drag to that position
#this is the where the function checks if the touch has moved. It first loops through every position of the tiles previously generated and compares that to the self.drag position set earlier. It then sets the self.touched_tile variable to that tile SpriteNode created earlier, which will then allow movement. After that it checks where the player's touch ends and compares that to the inital self.drag position. Then based on that touch movement, it moved the SpriteNode to the next position over in that direction.
def touch_moved(self, touch):
for i in self.tiles:
if i.position == self.drag:
self.touched_tile = i #checks to see if there is a tile at that position and sets it to the touched_tile variable
if touch.location[0] - self.drag[0] >= 50 and touch.location[1] <= touch.location[1] + self.MARGIN_OF_ERROR and touch.location[1] >= touch.location[1] - self.MARGIN_OF_ERROR: #checks to see if touch movement moves right
move_right = Action.move_to(self.drag[0] + 66, self.drag[1], 1, TIMING_SINODIAL) #sets how tile moves
for j in self.tiles:
if self.drag[0] + 66 > 680:
self.drag == False
self.touched_tile == None
print("Didn't move off gameboard")
return self.drag and self.touched_tile
elif self.drag[0] + 66 != j.position[0] and self.drag[1] == j.position[1]:
self.touched_tile.run_action(move_right)
self.drag == False
print("I moved right")
return self.touched_tile and self.drag
else:
self.drag == False
self.touched_tile == None
print("Failed")
return self.drag and self.touched_tile
elif touch.location[0] - self.drag[0] <= -50 and touch.location[1] <= touch.location[1] + self.MARGIN_OF_ERROR and touch.location[1] >= touch.location[1] - self.MARGIN_OF_ERROR: #checks to see if touch movement moves left
move_left = Action.move_to(self.drag[0] - 66, self.drag[1], 1, TIMING_SINODIAL)
for j in self.tiles:
if self.drag[0] - 66 < 440:
self.drag == False
self.touched_tile == None
print("Didn't move off gameboard")
return self.drag and self.touched_tile
elif self.drag[0] - 66 != j.position[0] and self.drag[1] == j.position[1]:
self.touched_tile.run_action(move_left)
self.drag == False
print("I moved left")
return self.touched_tile and self.drag
else:
self.drag == False
self.touched_tile == None
print("Failed")
return self.drag and self.touched_tile
elif touch.location[1] - self.drag[1] >= 50 and touch.location[0] <= touch.location[0] + self.MARGIN_OF_ERROR and touch.location[0] >= touch.location[0] - self.MARGIN_OF_ERROR: #checks to see if touch movement moves up
move_up = Action.move_to(self.drag[0], self.drag[1] + 66, 1, TIMING_SINODIAL)
for j in self.tiles:
if self.drag[1] + 66 > 530:
self.drag == False
self.touched_tile == None
print("Didn't move off gameboard")
return self.drag and self.touched_tile
elif self.drag[1] + 66 != j.position[1] and self.drag[0] == j.position[0]:
self.touched_tile.run_action(move_up)
self.drag == False
print("I moved up")
return self.touched_tile and self.drag
else:
self.drag == False
self.touched_tile == None
print("Failed")
return self.drag and self.touched_tile
elif touch.location[1] - self.drag[1] <= -50 and touch.location[0] <= touch.location[0] + self.MARGIN_OF_ERROR and touch.location[0] >= touch.location[0] - self.MARGIN_OF_ERROR: #checks to see if touch movement moves down
move_down = Action.move_to(self.drag[0], self.drag[1] - 66, 1, TIMING_SINODIAL)
for j in self.tiles:
if self.drag[1] - 66 < 300:
self.drag == False
self.touched_tile
print("Didn't move off gameboard")
return self.drag and self.touched_tile
elif self.drag[1] - 66 != j.position[1] and self.drag[0] == j.position[0]:
self.touched_tile.run_action(move_down)
self.drag == False
print("I moved down")
return self.touched_tile and self.drag
else:
self.drag == False
self.touched_tile == None
print("Failed")
return self.drag and self.touched_tile
#resets self.drag to intial False value for next touch to reset.
def touch_ended(self, touch):
if self.drag:
self.drag = False
return self.drag
#CHECK FOR LOOPS
if name == 'main':
run(Game(), PORTRAIT, show_fps=True)
)