Reputation: 595
I'm creating a program that makes a box move when I select it (By clicking) then clicking again where it needs to go. But this doesn't work. Instead the object moves a few pixels then stutters.
import pygame
import sys
import time
import Test_Class
from pygame import gfxdraw
pygame.init()
black = (1, 1, 1)
white = (255, 255, 255)
red = (255, 0, 0)
orange = (255, 130, 28)
light_orange = (255, 139, 36)
yellow = (231, 231, 42)
green2 = (0, 130, 15)
green = (0, 255, 0)
cyan = (60, 142, 176)
light_blue = (165, 165, 255)
blue = (0, 0, 255)
grey = (127, 127, 127)
light_grey = (191, 191, 191)
purple = (140, 57, 188)
brown = (112, 68, 37)
pink = (237, 167, 203)
dark_grey = (64, 64, 64)
display_width = 1260
display_height = 900
Bob = Test_Class.Army(400, 600)
game_display = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption("WW1 game")
clock = pygame.time.Clock()
def game_loop():
game_exit = False
while not game_exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
pygame.quit()
quit()
sys.exit()
game_display.fill(light_grey)
Bob.shape()
Bob.selection1()
Bob.movement()
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
sys.exit()
import pygame
import sys
import time
from pygame import gfxdraw
pygame.init()
black = (1, 1, 1)
white = (255, 255, 255)
red = (255, 0, 0)
orange = (255, 130, 28)
light_orange = (255, 139, 36)
yellow = (231, 231, 42)
green2 = (0, 130, 15)
green = (0, 255, 0)
cyan = (60, 142, 176)
light_blue = (165, 165, 255)
blue = (0, 0, 255)
grey = (127, 127, 127)
light_grey = (191, 191, 191)
purple = (140, 57, 188)
brown = (112, 68, 37)
pink = (237, 167, 203)
dark_grey = (64, 64, 64)
display_width = 1260
display_height = 900
game_display = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption("WW1 game")
clock = pygame.time.Clock()
class Army:
def __init__(self, posx, posy):
self.posx = posx
self.posy = posy
self.movex = posx
self.object = []
self.movey = posy
self.select = False
def shape(self):
gfxdraw.box(game_display, (self.posx, self.posy, 48, 30), black)
gfxdraw.box(game_display, (self.posx + 2, self.posy + 2, 43, 26), blue)
pygame.draw.line(game_display, black, (self.posx, self.posy + 1),
(self.posx + 47, self.posy + 28), 3)
def movement(self):
if self.movex > self.posx:
self.posx += 2
elif self.movex < self.posx:
self.posx -= 2
if self.movey > self.posy:
self.posy += 2
elif self.movey < self.posy:
self.posy -= 2
def selection1(self):
mouse = pygame.mouse.get_pos()
if self.posx + 48 > mouse[0] > self.posx and self.posy + 30 > mouse[1] > self.posy:
click = pygame.mouse.get_pressed()
if click[0] == 1:
gfxdraw.box(game_display, (self.posx + 2, self.posy + 2, 43, 26), light_blue)
pygame.draw.line(game_display, dark_grey, (self.posx, self.posy + 1), (self.posx + 47, self.posy + 28), 3)
self.select = True
while self.select is True:
click = pygame.mouse.get_pressed()
if click[0] == 1:
print("True")
mouse = pygame.mouse.get_pos()
self.movex = mouse[0]
self.movey = mouse[1]
self.select = False
pygame.display.update()
clock.tick(60)
Edit: Added everything required to test this.
Upvotes: 0
Views: 44
Reputation: 9756
The stutter happens if you click somewhere that's not divisible by 2, since you're tank is moving by 2 pixels each loop. So if you're clicking at x = 201 and your tank is at x = 200 it'll move to 202, and then back to 200 and repeat. Same is true for y.
A solution to the problem could be to add 1 to x or y if they're are odd. In other words: make it so the user's selected position only is in even numbers. Another solution could be to add the distance between for example posx and movex if the current distance is less than the amount of pixels the tank is moving. Like this:
def movement(self):
if self.movex > self.posx:
self.posx += 2 if abs(self.posx - self.movex) > 2 else abs(self.posx - self.movex)
elif self.movex < self.posx:
self.posx -= 2 if abs(self.posx - self.movex) > 2 else abs(self.posx - self.movex)
if self.movey > self.posy:
self.posy += 2 if abs(self.posy - self.movey) > 2 else abs(self.posy - self.movey)
elif self.movey < self.posy:
self.posy -= 2 if abs(self.posy - self.movey) > 2 else abs(self.posy - self.movey)
The problem is that you're checking if the mouse button is down, rather than if the mouse button is clicked. This means that if you're holding down the mouse button for longer than 1/60 ≈ 0.017 seconds, you're both selecting and moving the tank.
A solution could be to create two methods, select_tank and select_pos, which could be called in the event loop when the user presses the mouse button. I split your method selection1 and took away som unnecessary code. Also, notice that I put a line of code in draw to make it change color depending on whether it's selected or not.
class Army(object):
def __init__(self, posx, posy):
self.posx = posx
self.posy = posy
self.movex = posx
self.movey = posy
self.select = False
def draw(self):
color = blue if not self.select else light_blue
gfxdraw.box(game_display, (self.posx, self.posy, 48, 30), black)
gfxdraw.box(game_display, (self.posx + 2, self.posy + 2, 43, 26), color)
pygame.draw.line(game_display, black, (self.posx, self.posy + 1),(self.posx + 47, self.posy + 28), 3)
def move(self):
if self.movex > self.posx:
self.posx += 2 if abs(self.posx - self.movex) > 2 else abs(self.posx - self.movex)
elif self.movex < self.posx:
self.posx -= 2 if abs(self.posx - self.movex) > 2 else abs(self.posx - self.movex)
if self.movey > self.posy:
self.posy += 2 if abs(self.posy - self.movey) > 2 else abs(self.posy - self.movey)
elif self.movey < self.posy:
self.posy -= 2 if abs(self.posy - self.movey) > 2 else abs(self.posy - self.movey)
def select_tank(self):
mouse = pygame.mouse.get_pos()
if self.posx + 48 > mouse[0] > self.posx and self.posy + 30 > mouse[1] > self.posy:
self.select = True
def select_pos(self):
mouse = pygame.mouse.get_pos()
self.movex = mouse[0]
self.movey = mouse[1]
self.select = False
def game_loop():
game_exit = False
while not game_exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
elif event.type == pygame.MOUSEBUTTONDOWN:
if bob.select:
bob.select_pos()
else:
bob.select_tank()
game_display.fill(light_grey)
bob.move()
bob.draw()
pygame.display.update()
clock.tick(60)
if __name__ == "__main__":
.clock.tick
method even if you're doing it in the game loop.import time
(since you're not using it) and self.object
in the Army class (also unused). It would make the code a bit shorter and thus slightly easier to read.Upvotes: 1