1 Replies - 1485 Views - Last Post: 02 March 2009 - 08:03 PM Rate Topic: -----

#1 MattRam08   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 21
  • Joined: 26-January 09

Python help

Posted 02 March 2009 - 04:06 PM

I am trying to add an object every two seconds, but when I do my program either crashes or doesn't do what its supposed to.

Here is my program so far (its not finished yet of course):
import pygame
import time
import math
import random

# classes
class ship(object):
	def __init__(self, new_x, new_y):
		self.x = new_x
		self.y = new_y
		# the next 2 attributes are the velocity vector.
		self.vx = 0.0
		self.vy = 0.0
		self.angle = 90
		self.dist = 50
		
	def rotate(self, angle_rate, delta_t):
		self.angle += angle_rate * delta_t
		
	def render(self, surf):
		ax = self.x + self.dist * math.cos(math.radians(self.angle))
		ay = self.y + -self.dist * math.sin(math.radians(self.angle))
		bx = self.x + self.dist * math.cos(math.radians(self.angle + 150))
		by = self.y + -self.dist * math.sin(math.radians(self.angle + 150))
		cx = self.x + self.dist * math.cos(math.radians(self.angle - 150))
		cy = self.y + -self.dist * math.sin(math.radians(self.angle - 150))
		pygame.draw.polygon(surf, (0,255,0), ((ax, ay), (bx, by), (cx, cy)), 0)
		pygame.draw.circle(surf, (255,255,255), (self.x, self.y), 50, 3)
		
	def move(self, ship_speed, delta_t):
		#self.speed = ship_speed
		#self.x += self.speed * delta_t * math.cos(math.radians(self.angle))
		#self.y += -self.speed * delta_t * math.sin(math.radians(self.angle))
		dist = ship_speed * delta_t
		# Calculate the acceleration
		ax = dist * math.cos(math.radians(self.angle))
		ay = dist * math.sin(math.radians(self.angle))
		# Use acceleration to change velocity
		self.vx += ax
		self.vy += ay
		
	def update(self, delta_t):
		# use velocity to move
		self.x += self.vx * delta_t
		self.y -= self.vy * delta_t
		if self.x >= 799:
			self.x = 0
		if self.y >= 599:
			self.y = 0
		if self.x < 0:
			self.x = 799
		if self.y < 0:
			self.y = 599

	def hit_detect(self, other_x, other_y, other_rad):
		d = ((other_x - self.x)**2 + (other_y - self.y)**2)**0.5

class ring(object):
	def __init__(self, time):
		self.x = random.randint(30, 799 - 30)
		self.y = random.randint(30, 599 - 30)
		self.angle = 0 #math.radians(0)
		self.value = random.randint(1,8)
		self.time = time
		
	def render(self, surf):
		s_factor = 1.5 * math.sin(self.time) + 2.0
		radius_i = int(s_factor * 20)
		radius_o = int(s_factor * 24)
		pygame.draw.circle(surf, (255,0,0), (self.x,self.y), radius_o, radius_o - radius_i)
		#pygame.draw.circle(surf, (0,0,0), (self.x,self.y), radius_i, 0)

		# lines on rings
		#ax = self.x + radius_i * math.cos(self.angle)
		#ay = self.y - radius_i * math.sin(self.angle)
		#bx = self.x + radius_o * math.cos(self.angle)
		#by = self.y - radius_o * math.sin(self.angle)
		#pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)

		cur_angle = self.angle
		while cur_angle < self.angle + 360:
			ax = self.x + radius_i * math.cos(math.radians(cur_angle))
			ay = self.y - radius_i * math.sin(math.radians(cur_angle))
			bx = self.x + radius_o * math.cos(math.radians(cur_angle))
			by = self.y - radius_o * math.sin(math.radians(cur_angle))
			pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)
			cur_angle += 360/self.value
				
##		elif self.value == 7:
##			pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)
##			self.angle += 360/7
##		elif self.value == 6:
##			pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)
##			self.angle += 360/self.value
##		elif self.value == 5:
##			pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)
##			self.angle += 360/5
##		elif self.value == 4:
##			pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)
##			self.angle += 30
##		elif self.value == 3:
##			pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)
##			self.angle += 30
##		elif self.value == 2:
##			pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)
##			self.angle += 30
##		elif self.value == 1:
##			pygame.draw.line(surf, (255,255,255), (ax, ay), (bx, by), 3)

	def rotate(self,delta_t):
		self.angle += delta_t

class asteroid(object):
	def __init__(self, x, y):
		self.x = x
		self.y = y
		# velocity
		self.vx = 0.0
		self.vy = 0.0
		self.angle = random.uniform(0, 360)
			
def hit (p, rings):
	# look for hits between the player and any ring
	p.shields_on = False
	for r in rings:
		if p.hit_detect(r.x, r.y, (1.5 * math.sin(r.time) + 2.0) * 15):
			# hit
			print "hit"
			rings.remove(r)
			p.shields_on = True

# main program
pygame.display.init()
pygame.font.init()
screen = pygame.display.set_mode((800,600))
game_over = False
font_obj = pygame.font.SysFont("Courier New", 20)
clock_obj = pygame.time.Clock()
s_time = time.time()
total_time = 0.0
r_list = []
score = 0

player = ship(400,300)

for i in range(5):
		r = ring(total_time)
		r_list.append(r)
		
# game loop
while not game_over:
	# clear the screen
	screen.fill((0,0,0))
	
	# update variables
	if pygame.event.peek(pygame.QUIT):
		game_over = True
		
	pygame.event.pump()
	pressed_list = pygame.key.get_pressed()
	if pressed_list[pygame.K_ESCAPE]:
		game_over = True

	elapsed = round(time.time() - s_time, 1)

	# update the clock
	delta_t = clock_obj.tick() / 1000.0
	fps = clock_obj.get_fps()
	total_time += delta_t

	# update the ship
	player.update(delta_t)

	# add rings
	#if total_time >= 2.0:
		# create a new ring
		#new_r = r()
		#r_list.append(new_r)

	# check for hits
	hit(player, r_list)

	# get keyboard input
	if pressed_list[pygame.K_UP]:
		player.move(200, delta_t)
	if pressed_list[pygame.K_LEFT]:
		player.rotate(90, delta_t)
	if pressed_list[pygame.K_RIGHT]:
		player.rotate(-90, delta_t)

	# draw the world
	player.render(screen)
	for j in r_list:
		j.render(screen)
		j.rotate(0.125)

	# add more rings
	if total_time >= 2.0:
		# create a new ring
		r_list.append(r)
		
	# display fps
	surf = font_obj.render("FPS = " + str(round(fps/10, 0)), False, (255,255,255))
	screen.blit(surf, (5,5))
		
	pygame.display.flip()

# shut down
pygame.display.quit()


I know its long and probably a lot of it is unnecessary, but it works so far. Excuse the commented out code. I use comments so I know what I tried that didn't work.

I'm trying to get a ring to appear every 2 seconds.

Is This A Good Question/Topic? 0
  • +

Replies To: Python help

#2 numerical_jerome   User is offline

  • D.I.C Head

Reputation: 12
  • View blog
  • Posts: 167
  • Joined: 16-September 07

Re: Python help

Posted 02 March 2009 - 08:03 PM

it looks like when "total_time" exceeds 2.0 seconds, it is not reset to zero, resulting in your test case being hit every subsequent iteration, this would be an easy fix:

	# add more rings
	if total_time >= 2.0:
		# create a new ring
		r_list.append(r)
		total_time = 0



on a performance note, you would probably be better off using time.sleep() for your time delay, rather than a delay loop.

First, unless you need micro-second accuracy (which you really can't hit with the python interpreter anyway), this will be more than accurate.

Second, where your delay loop sits needlessly burning clock cycles, time.sleep(N) will return control to the OS for integer N seconds, allowing other applications (and your background processes / daemons) to get some processing time in.

Third, I think you will find that this will substantially shorten your code, by removing all of the variables, loops, and test conditions currently driving your delay loop.

Finally, as a direct consequence of shorter code, you will have less to debug, track, maintain, and as you continue your project, experimenting with and modifying your code will be less of a chore and more fun.

as with pretty much all python methods, you can get usage details for time.sleep by typing the following into the toplevel:

>>> import time
>>> help(time.sleep)



Hope this helps,

-Jerome
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1