3

I’m fairly new to scripting and I have a high-level question of how to do something.

I want to design a simple game similar to space invaders, with these two main features for now:

  1. Bullets drop down from the top of the screen every second.
  2. The user can move the home ship around at the bottom line of the screen and dodge the bullets.

The issue is that I can't find a way to constantly move the bullets down while still getting input.

Most of the code from the main loop:

while true #gets user input and updates screen.
do
    read -r -sn1 -t 1 USERIN
    case $USERIN in
        D) moveleft ;;
        C) moveright ;;
    esac 
    updatescreen #(my code makes sure that at least a second has passed since the last "updatescreen" execution before running this)
done

I want the screen to update every second, independently of the user input. Right now, the program is choppy when it updates because sometimes it has to wait longer for the input to timeout. It would be nice to have a lower read timeout but if I lower it I get an error: "invalid timeout specification."

Is there a way around this or maybe a whole different program organization?

  • You'll probably need to use coprocesses, so you can run multiple codes concurrently. – Barmar Oct 22 '14 at 18:48
  • so is the question about shorter timeout? Because what you are doing looks good, event driven is the easiest. – ctrl-alt-delor Oct 22 '14 at 19:40
  • @richard The question was basically: How can I resolve this issue without lowering the timeout? Because that doesn't work on my version of Bash. – Sman865 Oct 22 '14 at 20:36
  • What version of bash? and did you try -t 0.5 (the manual says fractional, but 1/2 does not work, and 0.5 does). – ctrl-alt-delor Oct 25 '14 at 16:13
2

You need multi-threading. Have a look at GNU Parallel

1

I found a solution. Basically, you run the update loop in the background and have the main loop in the foreground. They can communicate with each other using trap/kill commands.

I uploaded a .sh file to github to give a full example.

Here's a modified outline of how it works though:

Note: you have to use ctrl-c to escape.

#!/bin/bash

update()
{
    trap "move_left;" $LEFT
    trap "move_right;" $RIGHT

    while true; do
         #output whatever needed
    done
}

read_in()
{
    trap "return;" SIGINT SIGQUIT

    while true; do
        read -s -n 1 key
        case key in
            C) kill -$RIGHT $game_pid ;;
            D) kill -$LEFT $game_pid ;;
        esac
    done
}

move_left()
{
    #update position variable
}

move_right()
{
    #update position variable
}

update &
game_pid=$!
read_in

kill -9 $game_pid

Use the example script linked above for a working example version but there you have it! Just took a little reworking of the program architecture.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.