"""
pygame7.py: First implementation of a pygame 2D Tile Engine
Author: Josh Madden
License: Public
Version: 14.05.08.0846
"""
# imports
import sys
import pygame
import exceptions
from pygame.locals import *
from string import Template
# constants
SCREEN_SIZE = (800, 600)
WHITE = (255, 255, 255)
TILE_W = 64
TILE_H = 64
MAP_TILE_W = 20
MAP_TILE_H = 20
SCREEN_TILE_W = 12
SCREEN_TILE_H = 9
SCREEN_CLIP = pygame.Rect(0, 0, SCREEN_TILE_W*TILE_W, SCREEN_TILE_H*TILE_H)
DISPLAY_TILE_POS = False
DEF_IMAGE = "grass64.png"
# exception classes
# interface functions
# classes
class Tile(pygame.sprite.Sprite):
def __init__(self, image, left, top):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image).convert()
self.abs_pos = [left*TILE_W, top*TILE_H]
self.rect = pygame.Rect(self.abs_pos[0], self.abs_pos[1], TILE_W, TILE_H)
def reset(self):
self.rect.top = 0;
self.rect.left = 0;
def showPos(self,font_object,surface):
self.txt_pos = self.rect.center
self.print_pos = self.abs_pos[0]/TILE_W, self.abs_pos[1]/TILE_H
self.msg_txt = Template('($x,$y)')
self.msg_txt = self.msg_txt.substitute(x = self.print_pos[0], y = self.print_pos[1])
self.pos_msg = font_object.render(self.msg_txt, False, (255,0,0), (0,0,0))
surface.blit(self.pos_msg, self.txt_pos)
class SpriteGroup(pygame.sprite.Group):
def __init__(self):
pygame.sprite.Group.__init__(self)
class ViewSpriteGroup(pygame.sprite.Group):
def __init__(self, camera, sprite_group):
pygame.sprite.Group.__init__(self)
self.dX = 0
self.dY = 0
for sprite in sprite_group:
if sprite.rect.top >= camera.top:
if sprite.rect.left >= camera.left:
if sprite.rect.right <= camera.right:
if sprite.rect.bottom <= camera.bottom:
self.add(sprite)
def clearViewable(self, camera, sprite_group):
for sprite in self:
sprite.rect.topleft = sprite.abs_pos
if sprite.rect.top <= camera.top:
self.remove(sprite)
if sprite.rect.bottom >= camera.bottom:
self.remove(sprite)
if sprite.rect.left <= camera.left:
self.remove(sprite)
if sprite.rect.right >= camera.right:
self.remove(sprite)
def updateViewable(self, camera, sprite_group):
for sprite in sprite_group:
if sprite.rect.top >= camera.top:
if sprite.rect.left >= camera.left:
if sprite.rect.right <= camera.right:
if sprite.rect.bottom <= camera.bottom:
self.add(sprite)
for sprite in self:
sprite.rect.top -= camera.top
sprite.rect.left -= camera.left
class Camera(pygame.Rect):
def __init__(self):
pygame.Rect.__init__(self, 0, 0, SCREEN_TILE_W*TILE_W, SCREEN_TILE_H*TILE_H)
def pan(self, dX, dY):
self.move_ip(dX, dY)
if self.left < -64:
self.left = -64
if self.right > (MAP_TILE_W * TILE_W)+64:
self.right = (MAP_TILE_W * TILE_W)+64
if self.top < -64:
self.top = -64
if self.bottom > (MAP_TILE_H * TILE_H)+64:
self.bottom = (MAP_TILE_H * TILE_H)+64
# internal functions & classes
def printCam(camera):
print "camera top: ", camera.top, "\n", "camera left: ", camera.left, "\n", "camera right: ", camera.right, "\n", "camera bottom: ", camera.bottom, "\n"
def printTilePos(sprite_group, font_object, surface):
for sprite in sprite_group:
sprite.showPos(font_object, surface)
def main():
pygame.init()
pygame.display.set_mode(SCREEN_SIZE)
pygame.font.init()
test_font = pygame.font.Font(None, 15)
sprite_group = SpriteGroup()
camera = Camera()
for x in range(MAP_TILE_W):
for y in range(MAP_TILE_H):
sprite_group.add(Tile(DEF_IMAGE, x, y))
view_sprite_grp = ViewSpriteGroup(camera, sprite_group)
screen = pygame.display.get_surface()
screen.set_clip(SCREEN_CLIP)
screen.fill(WHITE)
pygame.display.flip()
printCam(camera)
while 1:
#handle events
for event in pygame.event.get():
#handle quit events
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
sys.exit()
#handle arrow key scrolling
if event.type == KEYDOWN and event.key == K_DOWN:
camera.pan(0,64)
printCam(camera)
if event.type == KEYDOWN and event.key == K_UP:
camera.pan(0,-64)
printCam(camera)
if event.type == KEYDOWN and event.key == K_LEFT:
camera.pan(-64,0)
printCam(camera)
if event.type == KEYDOWN and event.key == K_RIGHT:
camera.pan(64,0)
printCam(camera)
# Toggle displaying of tile position text
if event.type == KEYDOWN and event.key == K_F2:
if DISPLAY_TILE_POS == False:
DISPLAY_TILE_POS = True
else:
DISPLAY_TILE_POS = False
# Handle mouse scrolling
if event.type == MOUSEMOTION and event.pos[0] <= SCREEN_CLIP.left + 16:
camera.pan(-8,0)
printCam(camera)
if event.type == MOUSEMOTION and event.pos[0] >= SCREEN_CLIP.right - 16:
camera.pan(8,0)
printCam(camera)
if event.type == MOUSEMOTION and event.pos[1] <= SCREEN_CLIP.top + 16:
camera.pan(0,-8)
printCam(camera)
if event.type == MOUSEMOTION and event.pos[1] >= SCREEN_CLIP.bottom - 16:
camera.pan(0,8)
printCam(camera)
#update all sprites:
screen.fill(WHITE)
view_sprite_grp.updateViewable(camera, sprite_group)
#draw all sprites:
view_sprite_grp.draw(screen)
try:
if DISPLAY_TILE_POS == True:
printTilePos(view_sprite_grp, test_font, screen)
except UnboundLocalError:
DISPLAY_TILE_POS = False
#update the display
pygame.display.flip()
view_sprite_grp.clearViewable(camera, sprite_group)
#program entry point
if __name__ == '__main__':
status = main()
sys.exit(status)
Experienced pygame users please check my first-run of tile engine
ALCON:
I have been playing with game programming for some time, but recently decided to try the pygame 1.8 library for python. I have hacked together a basic 2D tile engine that implements mouse and key based scrolling. I have a long TODO list on this project, but I thought I should show what i've got so far and let anyone who's better at this than I am make suggestions and/or comments:
Edit: GDNet's [source] tag has rudimentary support for Python. Use [source lang="python"] - Oluseyi
In order to post python code, you should place it within
tags and post a link to a downloadable file. Python code uses whitespace as syntax. The whitespace has been stripped from your post, so what you've posted won't run.
class SpriteGroup(pygame.sprite.Group): def __init__(self): pygame.sprite.Group.__init__(self)
A very pointless class. If you want a shorter name, you can say
SpriteGroup=pygame.sprite.Group
camera.pan(0,-64)
if self.left < -64: self.left = -64if self.right > (MAP_TILE_W * TILE_W)+64: self.right = (MAP_TILE_W * TILE_W)+64
if event.type == MOUSEMOTION and event.pos[0] <= SCREEN_CLIP.left + 16: camera.pan(-8,0)
test_font = pygame.font.Font(None, 15)
You should define constants (or variables) in place of scattered and repeated naked numbers like these; using TILE_W and + 64 in the same line is particularly sad.
What if you decide to scale your fonts less blindly? A real game is going to have much more complex text drawing.
What if mouse scrolling speed becomes an user option?
What if multiple tile sizes (e.g. magnified for large screens) need to be supported?
Those are excellent points, precisely why I wanted to post this code for community examination. I originally created the SpriteGroup class as an extension to pygame.sprite.group, thinking I might at some point in the future extend the class. It is the base class that I use to store all sprites from which I can pull to display on the screen. I appreciate the feedback.
grazie mille
This is a FNG question, but what do I need to include in the post exactly for the python code to show up with the proper indentations and so forth?
grazie mille
This is a FNG question, but what do I need to include in the post exactly for the python code to show up with the proper indentations and so forth?
Quote:Original post by cyrex562
This is a FNG question, but what do I need to include in the post exactly for the python code to show up with the proper indentations and so forth?
[source lang="python"]<Python code here>[/source]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement