Author Topic: some getting-started python questions  (Read 11008 times)

joeclark77

  • Rogueliker
  • ***
  • Posts: 90
  • Karma: +0/-0
    • View Profile
some getting-started python questions
« on: February 23, 2013, 03:36:57 AM »
Hi all.  I've set out to create my first roguelike in Python, which I'm learning as I go.  I have many years of programming experience with web scripts, statistical stuff in R, etc, but never with stand-alone applications or graphics, so I'm not very familiar with game programming.  I'd like to pose a few questions to those who know something about this, in order to help me get started.

First: I don't want to use curses but would rather make a simulated-ascii game (i.e. use tiles that just look like ASCII characters).  This is because in the long run I want to use alternate tilesets, let the user resize the window, and do some funny stuff like arrange my map on a hexagonal grid. 

What librar(y/ies) should I use to implement this?  A "graphics" library like SDL or OpenGL?  Or a "GUI" library like tkinter?  I really have no idea about this stuff.
Bonus points: Can you get me started by showing me, in 3 or 4 lines of python, how to open a window and paint a tile to the screen with your recommended library?

Second: One problem I anticipate is that it might be difficult to print text to the screen, and to receive text input (eg. "enter a name for your character:") when I'm not really using text but actually a sequence of little graphical tiles.  Is this a major challenge, or is there an easy solution?

I guess those are my only questions to start with.  FYI, my vision is for a kind of settlement-simulator in the genre of Dwarf Fortress, but with a medieval theme.

kraflab

  • Rogueliker
  • ***
  • Posts: 454
  • Karma: +0/-0
    • View Profile
    • kraflab.com
Re: some getting-started python questions
« Reply #1 on: February 23, 2013, 05:49:32 AM »

Second: One problem I anticipate is that it might be difficult to print text to the screen, and to receive text input (eg. "enter a name for your character:") when I'm not really using text but actually a sequence of little graphical tiles.  Is this a major challenge, or is there an easy solution?


Whatever library you end up with is going to have a method for receiving key input, so entering a name is as simple as checking any other controls.  Of course, you won't be using the simplicity of reading stdin, but it's not at all difficult.  Some libraries will have taken this a step further and allow you to take a keyboard event and process that into logical text (a nice abstraction if you want to make sure you collect odd characters from foreign keyboards), but it isn't too hard to set up yourself if need be.

Wrt which library works I can't help you because I don't use python.  I've heard of http://www.pygame.org/news.html, but I don't know anything about it.

george

  • Rogueliker
  • ***
  • Posts: 201
  • Karma: +1/-1
    • View Profile
    • Email
Re: some getting-started python questions
« Reply #2 on: February 23, 2013, 09:28:06 PM »
Libtcod is the go-to RL library for a lot of people using Python.

joeclark77

  • Rogueliker
  • ***
  • Posts: 90
  • Karma: +0/-0
    • View Profile
Re: some getting-started python questions
« Reply #3 on: February 23, 2013, 09:32:43 PM »
Libtcod is the go-to RL library for a lot of people using Python.
I've heard that, but I don't like the fact that it has so much stuff (pathfinding, map generation algorithms, etc) built in.  I'd rather go with something minimalist so that I program those things myself at least once.  I'm looking more for a learning experience than for efficiency.

I'm wary of Pygame for the same reason -- does it do too much stuff that I don't need?  This one is a harder call.

I appreciate the feedback.

Quendus

  • Rogueliker
  • ***
  • Posts: 447
  • Karma: +0/-0
  • $@ \in \{1,W\} \times \{1,H\}$
    • View Profile
    • Klein Roguelikes
Re: some getting-started python questions
« Reply #4 on: February 23, 2013, 09:50:24 PM »
They're not so much "built in" as "available". There's nothing stopping you from using libtcod for display only, and coding your own map data structures, pathfinding, map generation, and field of vision.

george

  • Rogueliker
  • ***
  • Posts: 201
  • Karma: +1/-1
    • View Profile
    • Email
Re: some getting-started python questions
« Reply #5 on: February 23, 2013, 09:59:37 PM »
I can appreciate choosing a minimal library. Fwiw, I always liked the API of Pyglet over Pygame.

joeclark77

  • Rogueliker
  • ***
  • Posts: 90
  • Karma: +0/-0
    • View Profile
Re: some getting-started python questions
« Reply #6 on: February 24, 2013, 12:47:24 PM »
I can appreciate choosing a minimal library. Fwiw, I always liked the API of Pyglet over Pygame.

Thanks, that's one I haven't heard of.  The website provides a "hello world" example, too, which is just what I was hoping for.  Do we know of any examples of roguelikes written with pyglet?  (It would be nice to confirm that it works across platforms without too much hassle.)

george

  • Rogueliker
  • ***
  • Posts: 201
  • Karma: +1/-1
    • View Profile
    • Email
Re: some getting-started python questions
« Reply #7 on: February 24, 2013, 07:09:47 PM »
Not off the top of my head. If I were you I'd search at github, Pyweek, and Ludum Dare.

AgingMinotaur

  • Rogueliker
  • ***
  • Posts: 805
  • Karma: +2/-0
  • Original Discriminating Buffalo Man
    • View Profile
    • Land of Strangers
Re: some getting-started python questions
« Reply #8 on: February 27, 2013, 08:46:41 PM »
I think pygame is pretty nice. It certainly never got in my way, while still offering lots of functionality. This example should work if you copy and paste it:

Code: [Select]
import pygame
x_res=400
y_res=200
fullscreen=False
if fullscreen:
   screen=pygame.display.set_mode((x_res,y_res),(pygame.FULLSCREEN))
else:
   screen=pygame.display.set_mode((x_res,y_res))
pygame.display.set_caption("The greatest game never made")
screen.fill((200,200,200)) # make screen light grey

# 2. Draw a tile
tile_path="where/is/your/file.png" # path to your image
image=pygame.image.load(tile_path)
start_x,start_y=10,10 # start position measured in pixels from top left
screen.blit(image,(start_x,start_y)) # puts image on screen
pygame.display.flip() # renders to your actual monitor

# 3. zzzz
while 1:
   event=pygame.event.wait()
   if event.type==pygame.KEYDOWN: # as soon as you press down a key
       slartibartfast # exit gracefully :-)

As always,
Minotauros
This matir, as laborintus, Dedalus hous, hath many halkes and hurnes ... wyndynges and wrynkelynges.

joeclark77

  • Rogueliker
  • ***
  • Posts: 90
  • Karma: +0/-0
    • View Profile
Re: some getting-started python questions
« Reply #9 on: February 27, 2013, 09:13:47 PM »
Thanks, I'm starting to get the hang of using pyglet.  One thing that bugs the heck out of me, though, is that x and y coordinates in pyglet start from the bottom left.  That's the way it works in math, of course, but doesn't click with me.  I'm used to thinking of data structures as being in rows and columns starting from the top left.  So either I have to structure my map data "backwards" or program my display function to read the data backwards.

This admittedly ugly code works to produce a simple @ moving around a hex map (to run it, you need to steal a sprite set from dwarf fortress and put it in a 'resources' folder).  The nice thing about pyglet is that it has no dependencies, so you don't need to install SDL or any other libraries.

import pyglet
from pyglet.window import key
pyglet.resource.path = ['resources','resources/tiles']

window = pyglet.window.Window()

# IMPORT GRAPHICS
sprites = pyglet.resource.image("curses_800x600.png")
spriteset = pyglet.image.ImageGrid(sprites,16,16)
# re-organize the list because pyglet reads it in a bizarre way
spriteset = [spriteset[x:x+16] for x in range(0,len(spriteset),16)] #chunk into "rows"
spriteset = spriteset[::-1] # reverse the order of columns
#access by [row][column]

# figure out map dimensions and make a hex map of the background sprite(s)
w,h = sprites.width//16, sprites.height//16 # sprite dimensions
ww, wh = window.width, window.height # window dimensions
ncol, nrow = ww//w, wh//h # maximum columns/rows we could squeeze onto the screen
mapbatch = pyglet.graphics.Batch()
maptiles = []
for r in range(nrow):
    if r % 2:   # odd rows are shorter
        for c in range(ncol-1):
            maptiles.append( pyglet.sprite.Sprite( spriteset[15][10], x=(w*c)+(w//2), y=h*r, batch=mapbatch ) )
    else: # even rows are longer
        for c in range(ncol):
            maptiles.append( pyglet.sprite.Sprite( spriteset[15][10], x=w*c, y=h*r, batch=mapbatch ) )


atsign = pyglet.sprite.Sprite(spriteset[4][0],x=window.width//2, y=window.height//2)

fps_display = pyglet.clock.ClockDisplay()
  
@window.event
def on_draw():
    window.clear()
    mapbatch.draw()
    atsign.draw()
    fps_display.draw()

@window.event
def on_key_press(symbol, modifiers):
    moves = { key.LEFT:(-w,0), # num-lock off
              key.RIGHT:(w,0),
              key.HOME:(-w//2,h),
              key.PAGEUP:(w//2,h),
              key.END:(-w//2,-h),
              key.PAGEDOWN:(w//2,-h),
              key.NUM_4:(-w,0), # num-lock on
              key.NUM_6:(w,0),
              key.NUM_7:(-w//2,h),
              key.NUM_9:(w//2,h),
              key.NUM_1:(-w//2,-h),
              key.NUM_3:(w//2,-h)
              }  # symbol : (x move,y move)
    # these next lines break if the symbol isn't in the dictionary just created
    atsign.x += moves[symbol][0]  # horizontal movement
    atsign.y += moves[symbol][1]  # vertical movement
    print("key "+str(symbol)+": move "+str(moves[symbol]))

   
pyglet.app.run()


« Last Edit: February 27, 2013, 09:18:09 PM by joeclark77 »