0

I'm trying to make a game that resembles "Falldown," a TI-83 calculator game that I used to play in high school, using the curses library in Python. It involves a forever falling ball that you have to manoeuvre through holes and if you don't make it to the hole, the ball will get squished at the top of the screen (YouTube it).

So far, I just have an Obstacle class that doesn't even have holes yet. I just want my obstacles to be forever "scrolling up". I can make it work for one obstacle (obs1) but when I try to add a second (obs2), bad things happen. In the code below, both obstacles are on the screen but they are right on top of each other so it only looks like one obstacle.

Basically, how can I start my obs2 when obs1 reaches halfway up the screen?

#!/usr/bin/python

import curses
import time
import random

class obstacle:
  def __init__(self):
    self.pos = dims[0]-1
    self.s = ''
    for x in range(0,dims[1]-1):
      self.s += '='

  def scroll(self):
    self.pos -= 1


screen = curses.initscr()

curses.start_color()
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
screen.nodelay(1)
dims = screen.getmaxyx()

q=-1
obs1 = obstacle()
obs2 = obstacle()

while q < 0:
  q = screen.getch()
  if obs1.pos < 0:
    obs1 = obstacle()
  if obs2.pos < 0:
    obs2 = obstacle()
  screen.clear()
  screen.addstr(obs1.pos, 0, obs1.s, curses.color_pair(1))
  screen.addstr(obs2.pos, 0, obs2.s, curses.color_pair(1))
  obs1.scroll()
  obs2.scroll()
  screen.refresh()
  time.sleep(.04)
screen.getch()
curses.endwin()

Eventually I will want about 4 obstacles on the screen at once, forever scrolling upwards. Any hints to get me started with 2?

Keith Pinson
  • 7,835
  • 7
  • 61
  • 104
cursesNOOB
  • 11
  • 6
  • 1
    It seems like you've just created two `obstacle` objects, and done the exact same calls on them every time. So they always have the same `pos`, which means obviously they're going to draw on top of each other. Did you want to randomize them, or pass in some initial values from somewhere, or…? Without knowing what exactly you want to do, it's hard to explain how to do it, but obviously you need to do _something_ to give them different `pos` values if you want them to have different positions… – abarnert Jan 25 '13 at 23:46
  • Yes, right now they are on top of each other. I've tried making the starting point of obs2 half way up the screen, but once it gets to the top, it starts back over half way up the screen(as expected). I've tried not starting obs2 until obs1.pos is half way up the screen, but once obs1 gets to the top, obs2 disappears and doesn't restart until obs1 is half way up the screen(as expected). Anything else I try causes the program to crash. I'm stuck =( – cursesNOOB Jan 26 '13 at 00:05
  • This isn't really a `curses` problem. It's about your basic logic. Once you think through what the rules are for what you want `obs2` to do, the `curses` part is trivial. Let me give an example in an answer. – abarnert Jan 26 '13 at 01:01

1 Answers1

0

You need to think through what you want. What is obs2 before obs1 has gotten halfway through the screen? Is it nothing? An obstacle that's off the screen? An obstacle that works normally, but just doesn't get drawn?

Whatever you decide is pretty easy to code. I'll pick the most difficult and show how to make it work: we won't even create obs2 until obs1 gets far enough. This means we have to check if obs2 is not None everywhere we use it, and then add a line somewhere that creates it at the appropriate time. So, something like this:

obs1 = obstacle()
obs2 = None

while q < 0:
  q = screen.getch()
  if obs1.pos < 0:
    obs1 = obstacle()
  if obs2 is not None and obs2.pos < 0:
    obs2 = obstacle()
  # Here's where we create obs2 on the fly
  if obs2 is None and obs1.pos == dims[0]/2:
    obs2 = obstacle()
  screen.clear()
  screen.addstr(obs1.pos, 0, obs1.s, curses.color_pair(1))
  if obs2 is not None:
    screen.addstr(obs2.pos, 0, obs2.s, curses.color_pair(1))
  obs1.scroll()
  if obs2 is not None:
    obs2.scroll()
  screen.refresh()
  time.sleep(.04)

Let's say instead we want to start obs2 offset a bit from obs1. In that case, we just want to construct it with a different pos the first time, and everything else is unchanged from your original code:

class obstacle:
  def __init__(self, offset=1.0):
    self.pos = int((dims[0]-1) * offset)
    self.s = ''
    for x in range(0,dims[1]-1):
      self.s += '='

  def scroll(self):
    self.pos -= 1

screen = curses.initscr()

curses.start_color()
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
screen.nodelay(1)
dims = screen.getmaxyx()

q=-1
obs1 = obstacle()
obs2 = obstacle(.5)

while q < 0:
  q = screen.getch()
  if obs1.pos < 0:
    obs1 = obstacle()
  if obs2.pos < 0:
    obs2 = obstacle()
  screen.clear()
  screen.addstr(obs1.pos, 0, obs1.s, curses.color_pair(1))
  screen.addstr(obs2.pos, 0, obs2.s, curses.color_pair(1))
  obs1.scroll()
  obs2.scroll()
  screen.refresh()
  time.sleep(.04)
screen.getch()
curses.endwin()
abarnert
  • 354,177
  • 51
  • 601
  • 671