Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

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?

share|improve this question
    
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. –  richard 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). –  richard Oct 25 '14 at 16:13

2 Answers 2

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

share|improve this answer

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.

up vote 0 down vote accepted

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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