another pygame problem. I've tried to make a square move around on the screen in a formation of a, well, square. It works fine: first it goes down, then it turns to right, then it starts going up, then left, but as it gets to the point where it's supposed to go down, it simply doesn't and instead continues forward and out of the screen. Here's what I think is the relevant part
import pygame
from pygame.locals import *
from render import *
from player import *
import sys
pygame.init()
class collisions():
square1x = 50
square1y = 60
direction1 = "down"
vel1y = 0
vel1x = 0
square2x = 0
square2y = 0
direction2 = -1
square3x = 0
square3y = 0
direction3 = -1
square4x = 0
square4y = 0
direction4 = -1
square5x = 0
square5y = 0
direction5 = -1
green = pygame.Color(0,255,0)
def hitbox():
red = pygame.Color(255,0,0)
time = 1000/50
playerhb = pygame.rect.Rect(playerObj.x, playerObj.y,20,20)
if collisions.square1x < 40:
collisions.direction1 = "down"
if collisions.square1y > 200:
collisions.direction1 = "right"
if collisions.square1x > 600:
collisions.direction1 = "up"
if collisions.square1y < 50:
collisions.direction1 = "left"
if collisions.direction1 == "down":
collisions.vel1y = 0.02*time
collisions.vel1x = 0
if collisions.direction1 == "right":
collisions.vel1x = 0.02*time
collisions.vel1y = 0
if collisions.direction1 == "up":
collisions.vel1y = -0.02*time
collisions.vel1x = 0
if collisions.direction1 == "left":
collisions.vel1x = -0.02*time
collisions.vel1y = 0
collisions.square1x = collisions.square1x+collisions.vel1x
collisions.square1y = collisions.square1y+collisions.vel1y
enemy = pygame.rect.Rect(collisions.square1x,collisions.square1y,20,20)
draw(enemy,playerhb)
if enemy.colliderect(playerhb):
pygame.quit()
sys.exit()
pygame.display.flip()
Ignore all the other square coordinates and directions, I'm planning on making more of the squares move around on the screen.
There is a some problem with your sequence of "if". You cannot check only x or y axis in order to decide whether to change directions. You need to check both axis (or make sure the square goes back 1 pixel when the goal is reached).
I believe the code bellow will fix the problem with changing collisions.direction1.
if collisions.square1x < 40 and collisions.square1y < 50:
collisions.direction1 = "down"
if collisions.square1y > 200 and collisions.square1x < 40:
collisions.direction1 = "right"
if collisions.square1x > 600 and collision.square1y > 200:
collisions.direction1 = "up"
if collisions.square1y < 50 and collisions.square1x > 600:
collisions.direction1 = "left"
Related
I have created a simple simulation to show evolution. It works through a simuple window that contains many squares representing single-celled organisms. The screen looks like this:
The single-celled organisms (dubbed amoebae for conciseness) move around randomly. If they collide with another amoebae they produce an offspring. However, to prevent them reproducing infinitely I introduced an age measure. Amoebae must attain a certain age before they reproduce and once they do their age is reset to 1.
Now for the evolution part. As you can see, the amoebae are different colours. This represents the 'gene' that is passed down to offspring through reproduction (there is a chance of mutation controlled by a constant called maturingSpeed, which I set very high to increase the speed of evolution). It's called maturingSpeed and it controls the speed at which the amoebae age, which means that amoebae that have a higher maturingSpeed with reproduce faster and pass on their gene. In this way, they should gradually evolve through natural selection so all of the amoebae have a very high maturingSpeed. A high maturingSpeed translates to a brighter colour on the screen.
There is one other thing I should mention, which is the life countdown on each amoeba. It starts out at 10000 and ticks down by one each time the amoeba is updated. This is to gradually kill off the old amoebae, also increasing the rate of evolution and making it more lifelike.
My problem is that before the amoebae all evolve to get a high maturingSpeed (the highest I've had is around 65%), they become too numerous and the simulation starts slowing down as it struggles to load them all. I need a method to make the amoebae die off faster as more of them are produced. I have tried to cull them if they are above a certain number, or increase their countdown rate based on the number of amoebae however all of these methods cause them to eventually stop reproducing and die off for some reason. I have deleted these sections from my code now because they didn't work but I could add them again if needed.
My source code:
import pygame
import random
import time
import itertools
from pygame.locals import (
QUIT
)
pygame.init()
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 500
screen = pygame.display.set_mode([500, 500])
amoebas = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
idList = []
mutationConstant = 254
class Amoeba(pygame.sprite.Sprite):
id_iter = itertools.count()
def __init__(self, maturingSpeed, x, y):
super(Amoeba, self).__init__()
self.id = 'amoeba' + str(next(Amoeba.id_iter))
idList.append(self.id)
self.surf = pygame.Surface((10,10))
if maturingSpeed <= 0:
maturingSpeed = 1
elif maturingSpeed >= 255:
maturingSpeed = 254
print(maturingSpeed)
self.surf.fill((maturingSpeed, 0, 0))
self.rect = self.surf.get_rect(
center=(
x,
y,
)
)
self.speed = 2
self.age = 1
self.maturingSpeed = int(maturingSpeed)
self.life = 9999
def update(self):
if self.rect.left <= 0:
direction = 1
elif self.rect.right >= SCREEN_WIDTH:
direction = 2
elif self.rect.top <= 0:
direction = 3
elif self.rect.bottom >= SCREEN_HEIGHT:
direction = 4
else:
direction = random.randint(1, 4)
if direction == 1:
self.rect.move_ip(self.speed, 0)
elif direction == 2:
self.rect.move_ip(-self.speed, 0)
elif direction == 3:
self.rect.move_ip(0, self.speed)
elif direction == 4:
self.rect.move_ip(0, -self.speed)
self.life = self.life - 1
if self.life <= 0:
self.kill()
modMaturingSpeed = self.maturingSpeed / 1240
self.age = self.age + (1 * modMaturingSpeed)
#classmethod
def collide(cls):
global collisionSuccess
collisionSuccess = False
global posList
posList = [[amoeba.rect.left, amoeba.rect.bottom] for amoeba in amoebas]
length = len(posList)
for i in range(length):
for amoeba in amoebas:
if amoeba.id == str(idList[i]):
ageOne = getattr(amoeba, 'age')
for h in range(i+1, length):
for amoeba in amoebas:
if amoeba.id == str(idList[h]):
ageTwo = getattr(amoeba, 'age')
OneX = int(posList[i][0])
OneY = int(posList[i][1])
TwoX = int(posList[h][0])
TwoY = int(posList[h][1])
if ageOne >= 100 and ageTwo >= 100:
if (OneX < TwoX + 10 and OneX + 10 > TwoX
and OneY < TwoY + 10 and 10 + OneY > TwoY):
for amoeba in amoebas:
if amoeba.id == str(idList[i]):
setattr(amoeba, 'age', 1)
pOMSinitial = int(getattr(amoeba, 'maturingSpeed'))
for amoeba in amoebas:
if amoeba.id == str(idList[h]):
setattr(amoeba, 'age', 1)
pTMSinitial = int(getattr(amoeba, 'maturingSpeed'))
locationX = OneX + random.randint(-10, 10)
locationY = OneY + random.randint(-10, 10)
if pOMSinitial >= pTMSinitial:
pOMSfinal = pOMSinitial + mutationConstant
pTMSfinal = pTMSinitial - mutationConstant
newMaturingSpeed = random.randint(pTMSfinal, pOMSfinal)
else:
pOMSfinal = pOMSinitial - mutationConstant
pTMSfinal = pTMSinitial + mutationConstant
newMaturingSpeed = random.randint(pOMSfinal, pTMSfinal)
collisionSuccess = True
return cls(newMaturingSpeed, locationX, locationY)
screen.fill((255, 255, 255))
for i in range(15):
amoebaname = Amoeba(random.randint(100, 150), random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
amoebas.add(amoebaname)
all_sprites.add(amoebaname)
p = 0
while True:
ageArray = [amoeba.age for amoeba in amoebas]
if p == 1000:
print(amoebas)
five = 0
four = 0
three = 0
two = 0
one = 0
for amoeba in amoebas:
if amoeba.maturingSpeed >= 200:
five = five + 1
elif amoeba.maturingSpeed >=150:
four = four + 1
elif amoeba.maturingSpeed >= 100:
three = three + 1
elif amoeba.maturingSpeed >= 50:
two = two + 1
else:
one = one + 1
total = one + two + three + four + five
DivFive = five / total
DivFour = four / total
DivThree = three / total
DivTwo = two / total
DivOne = one / total
print(DivFive, DivFour, DivThree, DivTwo, DivOne)
p = 0
else:
p = p + 1
time.sleep(0.0000001)
screen.fill((255, 255, 255))
for event in pygame.event.get():
if event.type == QUIT:
break
amoebas.update()
amoebaname = Amoeba.collide()
if collisionSuccess == True:
amoebas.add(amoebaname)
all_sprites.add(amoebaname)
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
pygame.display.flip()
pygame.quit()
Too many nested loops and unneeded data structures. I did some cleanup and it's faster now. And it seems that the mutation constant was far to high. I changed the value from 254 to 25.
import pygame
import random
import time
import itertools
from pygame.locals import (
QUIT
)
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 500
MUTATION_CONSTANT = 25
pygame.init()
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
amoebas = pygame.sprite.Group()
class Amoeba(pygame.sprite.Sprite):
id_iter = itertools.count()
def __init__(self, maturing_speed, x, y):
super().__init__()
self.id = 'amoeba' + str(next(Amoeba.id_iter))
self.surf = pygame.Surface((10, 10))
self.maturing_speed = min(max(maturing_speed, 1), 254)
self.surf.fill((self.maturing_speed, 0, 0))
self.rect = self.surf.get_rect(center=(x, y,))
self.speed = 2
self.age = 1
self.life = 9999
def update(self):
if self.rect.left <= 0:
direction = 1
elif self.rect.right >= SCREEN_WIDTH:
direction = 2
elif self.rect.top <= 0:
direction = 3
elif self.rect.bottom >= SCREEN_HEIGHT:
direction = 4
else:
direction = random.randint(1, 4)
if direction == 1:
self.rect.move_ip(self.speed, 0)
elif direction == 2:
self.rect.move_ip(-self.speed, 0)
elif direction == 3:
self.rect.move_ip(0, self.speed)
elif direction == 4:
self.rect.move_ip(0, -self.speed)
self.life = self.life - 1
if self.life <= 0:
self.kill()
self.age = self.age + (1 * self.maturing_speed / 1240)
#classmethod
def collide(cls):
for amoeba_1, amoeba_2 in itertools.combinations(amoebas, 2):
if amoeba_1.age >= 100 and amoeba_2.age >= 100 and (
pygame.sprite.collide_rect(amoeba_1, amoeba_2)
):
amoeba_1.age = 1
amoeba_2.age = 1
location_x = amoeba_1.rect.left + random.randint(-10, 10)
location_y = amoeba_1.rect.bottom + random.randint(-10, 10)
speed_low = min(amoeba_1.maturing_speed, amoeba_2.maturing_speed) - MUTATION_CONSTANT
speed_high = max(amoeba_1.maturing_speed, amoeba_2.maturing_speed) + MUTATION_CONSTANT
new_maturing_speed = random.randint(speed_low, speed_high)
return cls(new_maturing_speed, location_x, location_y)
return None
def main():
screen.fill((255, 255, 255))
for i in range(25):
amoeba = Amoeba(random.randint(100, 150), random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
amoebas.add(amoeba)
step_counter = 0
while True:
step_counter += 1
if step_counter % 100 == 0:
print(step_counter, amoebas)
five = 0
four = 0
three = 0
two = 0
one = 0
for amoeba in amoebas:
if amoeba.maturing_speed >= 200:
five = five + 1
elif amoeba.maturing_speed >= 150:
four = four + 1
elif amoeba.maturing_speed >= 100:
three = three + 1
elif amoeba.maturing_speed >= 50:
two = two + 1
else:
one = one + 1
total = one + two + three + four + five
print(f'{five/total:.4f} {four/total:.4f} {three/total:.4f} {two/total:.4f} {one/total:.4f}')
time.sleep(0.0000001)
screen.fill((255, 255, 255))
for event in pygame.event.get():
if event.type == QUIT:
break
amoebas.update()
amoeba = Amoeba.collide()
if amoeba:
amoebas.add(amoeba)
for amoeba in amoebas:
screen.blit(amoeba.surf, amoeba.rect)
pygame.display.flip()
pygame.quit()
if __name__ == '__main__':
main()
In the past week I have downloaded pygame, and tried making different games, mainly following tutorials. As a project idea I have decided to make a game/simulation where mice and eagles move around the screen, eating, reproducing and trying to survive.
A vital part of the game is that each mouse must have individual information, like a variable for health, hunger and age. However, using my current code I am unware as to how I would do this, as I wish to have new mice spawn and added to a list of all the mice when certain events occur, with their individual info.
In other words, I am asking how I can give each 'given_mouse' unique variables that I can change when neccessary.
I have been trying different methods, and have done some googling but I have not yet come across a soloution, thanks in advance!
This is my code so far:
import pygame
import time
import random
import sys
import os
def mouse_animation(given_mouse):
global mouse_movement_counter, can_move_left, can_move_right, can_move_up, can_move_down
if given_mouse.x <= 20:
can_move_left = False
if given_mouse.x >= 1100:
can_move_right = False
if given_mouse.y <= 20:
can_move_up = False
if given_mouse.y >= 600:
can_move_down = False
direction = random.randint(1, 4)
if direction == 1 and mouse_movement_counter <= 0 and can_move_right:
given_mouse.x += 60
mouse_movement_counter += 30
elif direction == 2 and mouse_movement_counter <= 0 and can_move_up: #UP
given_mouse.y -= 60
mouse_movement_counter += 30
elif direction == 3 and mouse_movement_counter <= 0 and can_move_down: # DOWN
given_mouse.y += 60
mouse_movement_counter += 30
elif direction == 4 and mouse_movement_counter <= 0 and can_move_left: # LEFT
given_mouse.x -= 60
mouse_movement_counter += 30
elif direction == 5 and mouse_movement_counter <= 0:
mouse_movement_counter += 30
else:
mouse_movement_counter -= 1
pygame.display.update()
def random_postion():
global x_location, y_location
randomx_postion = random.randint(1,6)
if randomx_postion == 1:
x_location = 60
if randomx_postion == 2:
x_location = 120
if randomx_postion == 3:
x_location = 180
if randomx_postion == 4:
x_location = 240
if randomx_postion == 5:
x_location = 300
if randomx_postion == 6:
x_location = 360
randomy_postion = random.randint(1,6)
if randomy_postion == 1:
y_location = 60
if randomy_postion == 2:
y_location = 120
if randomy_postion == 3:
y_location = 180
if randomy_postion == 4:
y_location = 240
if randomy_postion == 5:
y_location = 300
if randomy_postion == 6:
y_location = 360
pygame.init()
clock = pygame.time.Clock()
FPS = 10
screen_width, screen_height = 1160, 680
screen = pygame.display.set_mode((screen_width, screen_height))
MOUSE_IMAGE = pygame.image.load(os.path.join("assets", "mouse.png"))
BG = pygame.transform.scale(pygame.image.load(os.path.join("assets", "background.png")), (screen_width,
screen_height))
mice = []
add_mouse = True
x_location = 0
y_location = 0
for i in range(40):
random_postion()
mouse = pygame.Rect(x_location, y_location, 40, 40)
mice.append(mouse)
mouse_movement_counter = 0
while True:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(BG, (0, 0))
for certain_mouse in range(len(mice)):
pygame.draw.rect(screen, (200, 200, 200), mice[certain_mouse])
mouse_loop = 0
while mouse_loop < len(mice):
can_move_right = True
can_move_left = True
can_move_up = True
can_move_down = True
mouse_animation(mice[mouse_loop])
mouse_loop += 1
pygame.display.flip()
Three ways I can think of. First one is to use a class for mouse.
class Mouse:
def __init__(self, age, health, hunger):
self.age = age
self.health = health
self.hunger = hunger
mice = []
if some_event_happens:
mice.append(Mouse(some_age, some_health, some_hunger))
If you are not familiar with classes yet, you can use a 2D array.
mice = []
if some_event_happens:
mice.append([some_age, some_health, some_hunger])
mice[index] gives you access to each mouse. mice[index][0] is age of mouse at that index, mice[index][1] is health of mouse at that index and mice[index][2] is hunger of mouse at that index.
Third way is to use a dictionary.
mice = []
if some_event_happens:
mice.append({"age": some_age, "health": some_health, "hunger": some_hunger})
I would personally prefer to use this to 2D array because there is no ambiguity on what indices mean as words are used instead of number which is clearer. Example
mice[index]["age"]
We are creating pacman in Python- tKinter(not in pygame) and the coins are not disappearing. I am not able to finish the program of random movement of koning(ghost).
It is supposed to change direction every 10 steps and not go out of the canvas. The coins are supposed to disappear after the pacman goes through the coin, it would disappear. The coins are supposed to be counted and be shown in the corner. After the 3 times the pacman meets the ghost, it would print ;Game over;.
sirka = 0
vyska = 0
koning_x = 0
koning_y = 0
```pome=coins
pome_x = 0
pome_y = 0
random_direction = random.randint(0,3)
counter = 10
def platne_pole (y, x) :
global sirka
global vyska
if (x > 0 and x < sirka - 1) and (y > 0 and y < vyska - 1):
return True
return False
def kmove (event):
global koning_x
global koning_y
global mapa
target_x = koning_x *cell_size
target_y = koning_y *cell_size
def posun (target_x, target_y, koning_smer):
if koning_smer == 0:
target_y -= 1
elif koning_smer == 1:
target_x += 1
elif koning_smer == 2:
target_y += 1
elif koning_smer == 3:
target_x == 1
return target_x, target_y
target_x, target_y = kmove(koning_x, koning_y, koning_smer)
I wanted turtle not to go out of square
the window comes out and no error but loading keeps and if I click the window, it shuts down.
x, y is turtle's location.
D is to show weather or not turtle is inside square and on line(?).
a is nothing
direction changes
speed changes
location check and change
if turtle's in line, it go along boundary.
import turtle
import msvcrt
turtle.setup(100, 100, 0, 0)
t = turtle.Turtle()
D = 0
a = 1
while True:
if msvcrt.kbhit():
c = msvcrt.getch().decode('UTF - 8')
if c == 'j': # turn left
t.left(10)
if c == 'k':
t.right(10)
if c == 'a':# speed change
a += 1
if a > 10: # speed limitation
a = 10
if c == 'z':
a += -1
if a < 0:
a = 0
#---------------------------------------
x = t.xcor() # turtle's location
y = t.ycor()
if x > 100: # if go out of square, go back to the square
t.setx(100)
if x < -100:
t.setx(-100)
if y > 100:
t.sety(100)
if y < -100:
t.sety(-100)
#---------------------------------------
x = t.xcor() # turtle's location
y = t.ycor()
h = t.heading() # turtle's direction
#---------------------------------------
if - 100 < x < 100 and -100 < y < 100:
D = 0 # if it's in the square, D = 0
elif x == 100 and -100 < y < 100: # if it's in ~
if 0 <= d <= 90: # direction changes
t.setheading(90) # direction change to 90 degrees
D = 1 # D = 1
elif 270 <= d < 360:
t.setheading(270)
D = 2
elif x == -100 and -100 < y < 100:
if 90 <= d < 180:
t.setheading(90)
D = 2
elif 180 <= d <= 270:
t.setheading(270)
D = 1
elif y == 100 and -100 < x < 100:
if 0 <= d < 90:
t.setheading(0)
D = 2
elif 90 <= d <= 180:
t.setheading(180)
D = 1
elif y == -100 and -100 < x < 100:
if 180 <= d < 270:
t.setheading(180)
D = 2
elif 270 <= d < 360:
t.setheading(0)
D = 1
elif D == 1:
t.left(90)
elif D == 2:
t.right(90)
This code is a mess. First, by setting your window size to 100 x 100 and then moving your turtle between -100 and 100 in both dimensions, only 1/4 of your field of play is visible! Why use the msvcrt module when turtle has perfectly good keyboard events built in? As far as I can tell, your code checks and corrects the turtle's position but never actually moves it! And you have a while True: loop which has no place in an event-driven environment like turtle.
Let's start over with a simple example of motion within a square which can be manipulated via the keyboard:
from turtle import Screen, Turtle
def turn_left():
turtle.left(10)
def turn_right():
turtle.right(10)
def speed_up():
speed = turtle.speed() + 1
if speed > 10: # speed limitation
speed = 10
turtle.speed(speed)
def slow_down():
speed = turtle.speed() - 1
if speed < 1: # speed limitation
speed = 1
turtle.speed(speed)
def move():
# there are two different senses of 'speed' in play, we'll exploit
# both! I.e. as we move faster, we'll draw faster and vice versa
turtle.forward(turtle.speed())
# if we go out of square, go back into the square
if not -100 < turtle.xcor() < 100:
turtle.undo()
turtle.setheading(180 - turtle.heading())
elif not -100 < turtle.ycor() < 100:
turtle.undo()
turtle.setheading(360 - turtle.heading())
screen.ontimer(move, 100)
screen = Screen()
screen.setup(300, 300)
# show turtle's boundary
boundary = Turtle('square', visible=False)
boundary.color('pink')
boundary.shapesize(10)
boundary.stamp()
turtle = Turtle()
move()
screen.onkey(turn_left, 'j')
screen.onkey(turn_right, 'k')
screen.onkey(speed_up, 'a')
screen.onkey(slow_down, 'z')
screen.listen()
screen.mainloop()
I'm making a game.
The game's world is represented by a tilemap. The tiles correspond to values in a 2D array.
I would like to use a special "corner" wall sprite if any three wall tiles make an L shape. That is,
V
## # >##
# ## #
^
The tiles indicated with arrows should be corner tiles.
I have the code to search for the wall but I don't know how to identify which tiles are the corner tiles.
My code is:
import pygame, sys
import Sprites
import random
from pygame.locals import *
pygame.init()
fpsClock = pygame.time.Clock()
cloudx = -200
cloudy = 0
infoObject = pygame.display.Info()
DIRT = 0
GRASS = 1
WATER = 2
COAL = 3
CLOUD = 4
WALL = 5
CWALL = 6
controls = {
DIRT : 49,
GRASS: 50,
WATER: 51,
COAL : 52,
WALL : 53
}
infoObject = pygame.display.Info()
w = infoObject.current_w
h = infoObject.current_h
TILESIZE = 40
MAPWIDTH = 15
MAPHEIGHT = 15
WHITE = (255,255,255)
BLACK = (0,0,0)
resources = [DIRT, GRASS, WATER, COAL]
textures = {
DIRT : pygame.image.load('Sprites/Dirt.png'),
GRASS : pygame.image.load('Sprites/tile130.png'),
WATER : pygame.image.load('Sprites/Water.png'),
COAL : pygame.image.load('Sprites/Coal.png'),
CLOUD : pygame.image.load('Sprites/Cloud.png'),
WALL : pygame.image.load('Sprites/Swall.png'),
CWALL : pygame.image.load('Sprites/Swall.png')
}
playerPos = [0,0]
inventory = {
DIRT : 0,
GRASS : 0,
WATER : 0,
COAL : 0,
WALL : 10,
}
tilemap = [[DIRT for w in range(MAPWIDTH)] for h in range(MAPHEIGHT)]
DISPLAYSURF = pygame.display.set_mode((MAPWIDTH*TILESIZE,MAPHEIGHT*TILESIZE + 50))
pygame.display.set_caption('M I N E C R A F T -- 2D')
pygame.display.set_icon(pygame.image.load('Sprites/player.png'))
PLAYER = pygame.image.load('Sprites/Player.png').convert_alpha()
for rw in range(MAPHEIGHT):
for cl in range(MAPWIDTH):
randomNumber = random.randint(0,15)
if randomNumber == 0:
tile = COAL
elif randomNumber == 1 or randomNumber == 2:
tile = WATER
elif randomNumber >= 3 and randomNumber <=7:
tile = GRASS
else:
tile = DIRT
tilemap[rw][cl] = tile
INVFONT = pygame.font.Font('freesansbold.ttf', 18)
print(tilemap)
while True:
currentTile = tilemap[playerPos[1]][playerPos[0]]
DISPLAYSURF.fill(BLACK)
for event in pygame.event.get():
# print(event)
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
for key in controls:
if (event.key == controls[key]):
if inventory[key] > 0:
inventory[key] -=1
inventory[currentTile] += 1
tilemap[playerPos[1]][playerPos[0]] = key
if(event.key == K_RIGHT) and playerPos[0] < MAPWIDTH - 1:
playerPos[0]+=1
elif(event.key == K_LEFT) and playerPos[0] > 0:
playerPos[0]-=1
elif(event.key == K_DOWN) and playerPos[1] < MAPHEIGHT - 1:
playerPos[1]+=1
elif(event.key == K_UP) and playerPos[1] > 0:
playerPos[1]-=1
if event.key == K_SPACE:
currentTile = tilemap[playerPos[1]][playerPos[0]]
inventory[currentTile] += 1
tilemap[playerPos[1]][playerPos[0]] = DIRT
for row in range(MAPHEIGHT):
for column in range(MAPWIDTH):
DISPLAYSURF.blit(textures[tilemap[row][column]],(column*TILESIZE, row*TILESIZE, TILESIZE, TILESIZE))
DISPLAYSURF.blit(PLAYER,(playerPos[0]*TILESIZE,playerPos[1]*TILESIZE))
DISPLAYSURF.blit(textures[CLOUD].convert_alpha(),(cloudx,cloudy))
cloudx +=1
if cloudx > MAPWIDTH*TILESIZE:
cloudy = random.randint(0, MAPHEIGHT*TILESIZE)
cloudx = -200
placePosition = 10
for item in resources:
DISPLAYSURF.blit(textures[item],(placePosition, MAPHEIGHT*TILESIZE+10))
placePosition+=50
textObj = INVFONT.render(str(inventory[item]), True, WHITE, BLACK)
DISPLAYSURF.blit(textObj,(placePosition, MAPHEIGHT*TILESIZE+20))
placePosition += 50
pygame.display.update()
fpsClock.tick(24)
for x in range(MAPWIDTH):
for y in range(MAPHEIGHT):
if tilemap[x][y] == WALL:
go_left = x > 1
go_right = x < MAPWIDTH - 1
go_up = y > 1
go_down = y < MAPHEIGHT - 1
if go_left:
tilemap[x - 1][y] = CWALL
if go_up:
pass
if go_right:
tilemap[x + 1][y] = WALL
if go_up:
pass
if go_down:
pass
print('WALL')
pygame.display.update()
And here are the links to the sprites:
https://framadrop.org/r/fmReup_rTK#bMSywSUa7nxb1qL/a4FIbns+VaspgE0c/FU+9f1drHI=
https://framadrop.org/r/pBOfrnKcdT#eNEZQ9QjX5Cl6X4gH4UwdIg3eBPnY/L4WcSGYtUR5PE=
https://framadrop.org/r/ZFfTz_Lq9V#2Nd5ba1iE7miyFg8JpPFvwabAkdnHds/GfVkSAQeJaQ=
https://framadrop.org/r/gN9Y748L9G#Z552pPpgjTcSubt9tn74mZ0tT1COv7UCFdkUq2DorAU=
https://framadrop.org/r/d9k4hyCUni#OTza8UbsR8Am/R1PA9MAWkLDPRDBsT1rAHMgr61jusc=
https://framadrop.org/r/1mv777OR6d#pkqwaQrmVRElUPcdEV5K4UhmALsJSYX7z3WtrZXl4TE=
https://framadrop.org/r/CyF-tk7yUb#IFexcePe418JizElZzCJzDENTJPDfz7i1nr+lGns0rU=
https://framadrop.org/r/VzVfAz6bnL#oLHivyHPtTD8+IxliDD4yc+6LS9kpGyEp1HNFGUsBHo=
https://framadrop.org/r/0V0ShMH0uq#PZHdPSQNbgL7QqH2niwdS4HO34ZRMfIlhpvpRqbWwng=
From the comments, I'm not sure what the problem is... let me just show you what I would do so we can discuss further if needed:
for x in range(MAPWIDTH):
for y in range(MAPHEIGHT):
if tilemap[x][y] == WALL:
# there is a wall at indices x and y
# get neighbouring tiles (check for limits)
go_left = x > 1
go_right = x < MAPWIDTH - 1
go_up = y > 1
go_down = y < MAPHEIGHT - 1
if go_left:
# you can use x-1
tilemap[x-1][y] = WALL # set left tile to WALL
if go_up:
# do something in the diagonal with x-1 y-1?
pass
if go_right:
# you can use x+1
tilemap[x+1][y] = WALL # set right tile to WALL
if go_up:
pass # same story
if go_down:
pass # and again
EDIT here is a simple (hence hopefully easy to understand) way of doing this
In order to make the textures clean, I first had to rotate the wall and corner to get all possible configurations (vertical/horizontal for the wall, and all four possibilities for the corner)
VWALL = 5
HWALL = 6
CORNERLD = 7
CORNERRD = 8
CORNERLU = 9
CORNERRU = 10
controls = {
DIRT : 49,
GRASS : 50,
WATER : 51,
COAL : 52,
VWALL : 53,
HWALL : 54,
CORNERLD: 55,
CORNERRD: 56,
CORNERLU: 57,
CORNERRU: 58,
}
tex_wall = pygame.image.load('Sprites/Swall.png')
tex_corner = pygame.image.load('Sprites/Corner.png')
textures = {
DIRT : pygame.image.load('Sprites/Dirt.png'),
GRASS : pygame.image.load('Sprites/tile130.png'),
WATER : pygame.image.load('Sprites/Water.png'),
COAL : pygame.image.load('Sprites/Coal.png'),
CLOUD : pygame.image.load('Sprites/Cloud.png'),
HWALL : pygame.transform.rotate(tex_wall, 90),
VWALL : tex_wall,
CORNERRD: tex_corner,
CORNERLD: pygame.transform.flip(tex_corner, True, False),
CORNERLU: pygame.transform.flip(tex_corner, True, True),
CORNERRU: pygame.transform.flip(tex_corner, False, True),
}
I created a wall dict to quickly check all 6 possibilities for walls with in walls
walls = {
VWALL : None,
HWALL : None,
CORNERLD: None,
CORNERRD: None,
CORNERLU: None,
CORNERRU: None,
}
And then I check the map
for x in range(MAPWIDTH):
for y in range(MAPHEIGHT):
if tilemap[x][y] in walls:
# there is a wall at indices x and y
# get neighbouring tiles (check for limits)
go_left = x > 1
go_right = x < MAPWIDTH - 1
go_up = y > 1
go_down = y < MAPHEIGHT - 1
l_wall = False
r_wall = False
u_wall = False
d_wall = False
if go_left and tilemap[x-1][y] in walls:
# left tile is WALL
l_wall = True
if go_right and tilemap[x+1][y] in walls:
# right tile is WALL
r_wall = True
if go_up and tilemap[x][y-1] in walls:
u_wall = True
if go_down and tilemap[x][y+1] in walls:
d_wall = True
if l_wall and u_wall:
# upper left corner
tilemap[x][y] = CORNERLU
elif l_wall and d_wall:
# down left corner
tilemap[x][y] = CORNERRU
elif r_wall and u_wall:
# upper left corner
tilemap[x][y] = CORNERLD
elif r_wall and d_wall:
# down left corner
tilemap[x][y] = CORNERRD
elif (l_wall or r_wall) and not (u_wall or d_wall):
# tiles in a vertical wall, use VWALL
tilemap[x][y] = VWALL
elif (u_wall or d_wall) and not (l_wall or r_wall):
# tiles in a horizontal wall, use HWALL
tilemap[x][y] = HWALL
And we get
Note that there are random configurations of wall that will not look good, though (T-shapes...) but these would require additional sprites.
The full code I used can be found here
EDIT2 note that you will have to update a few more things to make everything work smoothly (e.g. wall uptake in the inventory)
Also running this check every loop is costly, so you should declare an env_changed boolean to make the test only when a change was made to the environment.
For the inventory, you will need
if currentTile in walls:
inventory[VWALL] += 1
this makes VWALL the default wall in the inventory and the loop takes care of switching it to a proper one for the display.
For the rest, well... it's your game, so I'll let you figure it out ;)
I'd start by generating a set offsets
// 1
//0 2 Neighbour directions
// 3
// 0 1 2 3 Corresponding offsets
dx = [-1, 0, 1, 0]
dy = [0, -1, 0, 1]
Nmax = 4
Now, I can get the n-values of the neighbouring walls, like so:
nwalls = []
for n in range(Nmax): #n is the direction of the neighbour
#Ensure that the neighbour tile, identified as (x+dx[n], y+dy[n])
#is in the map and check to see if it is a wall
if 1<x+dx[n]<WIDTH and 1<y+dy[n]<HEIGHT and tilemap[x+dx[n]][y+dy[n]]==WALL:
nwalls.append(n) #Neighbour was a wall, add its direction to this list
Now, I can convert my list into a tile name:
#nwalls is a list of all the directions pointing to a wall
nwalls.sort() #Sort list, e.g. 3,1,2 -> 1,2,3
nwalls = map(str,nwalls) #Convert from numbers to strings
nwalls = ''.join(nwalls) #Append strings together: ['1','2','3'] -> '123'
if nwalls: #If the string is not empty
nwalls = 'corner_tile_{0}.jpg'.format(nwalls) #Convert string to tile name
Now I just need a bunch of tiles named, e.g.:
corner_tile_01.jpg
corner_tile_013.jpg
Then I can say:
if nwalls: #Only true if this was a corner
Code to display the tile whose name is stored in `nwalls`