
# This code creates the ICEM CFD Manager.
#
# Copyright (c) 1993 - 1996 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com

proc game_put_ship {} {
    global game_xpos game_ypos game_dir game_thrust
    
    set ship_shape {
	-10 0
	-10 -10
	10 -10
	10 -8
	30 -4
	30 0
	10 0
	10 2
	-10 2
	-10 0
    }
    
    set fire_shape {
	-10 -7
	-30 -3
	-10 1
	-10 -7
    }
    
    .game.c delete ship_tag
    
    set shape {}
    set which 0
    foreach c $ship_shape {
	if $which {
	    set c [expr {$game_ypos + $c}]; set which 0
	} else {
	    set c [expr {$game_xpos + $game_dir * $c}]; set which 1
	}
	lappend shape $c
    }
    set poly [eval .game.c create polygon $shape -fill blue]
    set line [eval .game.c create line $shape -fill yellow]
    
    .game.c addtag ship_tag withtag $poly
    .game.c addtag ship_tag withtag $line
    
    if $game_thrust {
	set shape {}
	set which 0
	foreach c $fire_shape {
	    if $which {
		set c [expr {$game_ypos + $c}]; set which 0
	    } else {
		set c [expr {$game_xpos + $game_dir * $c}]; set which 1
	    }
	    lappend shape $c
	}
	set poly [eval .game.c create polygon $shape -fill red]
	.game.c addtag ship_tag withtag $poly
    }
}

proc game_update {} {
    global game_xpos game_ypos game_xvel game_thrust game_mousex game_mousey
    global game_dir game_width game_height

    if {$game_xpos < 0} {set game_xvel [expr {-$game_xvel}]}
    if {$game_xpos > $game_width} {set game_xvel [expr {-$game_xvel}]}
    
    if $game_thrust {
	incr game_xvel $game_dir
	if {$game_xvel > 20} {set game_xvel 20}
	if {$game_xvel < -20} {set game_xvel -20}
    }
    incr game_xpos $game_xvel
    if [info exists game_mousey] {
	if {$game_mousey < $game_ypos} {incr game_ypos -10}
	if {$game_mousey > $game_ypos} {incr game_ypos 10}
    }
    game_put_ship
    update
}

proc game_make_splat {} {
    global game_xpos game_ypos game_ships
    
    set pts {}
    for {set i 0} {$i < 40} {incr i} {
	lappend pts [expr {$game_xpos + [game_random 100] - 50}]
	lappend pts [expr {$game_ypos + [game_random 100] - 50}]
    }
    set foo [eval .game.c create polygon $pts -fill orange]
    incr game_ships
    .game.ships configure -text "  Ship number: $game_ships   "    
    after 1000
    .game.c delete $foo
}

proc game_new_shot {} {
    global game_shot_y game_shot_x1 game_shot_x2 game_shot_speed
    global game_xpos game_ypos game_dir game_is_shot
    
    set line [.game.c create line $game_xpos $game_ypos $game_xpos $game_ypos -width 3 -fill green]
    set game_shot_y($line) $game_ypos
    set game_shot_x1($line) $game_xpos
    set game_shot_x2($line) $game_xpos
    set game_shot_speed($line) [expr {$game_dir * 50}]
    set game_is_shot($line) 1
}

proc game_shots {} {
    global game_shot_y game_shot_x1 game_shot_x2 game_shot_speed game_is_shot
    
    foreach l [array names game_shot_y] {
	incr game_shot_x2($l) $game_shot_speed($l)
	set len [expr {$game_shot_x2($l) - $game_shot_x1($l)}]
	if {($len < -200) || ($len > 200)} {
	    incr game_shot_x1($l) $game_shot_speed($l)
	} else {
	    incr game_shot_x1($l) [expr {$game_shot_speed($l) / 2}]
	}
	if {($game_shot_x1($l) < 0) || ($game_shot_x2($l) > 1000)} {
	    .game.c delete $l
	    unset game_is_shot($l)
	    foreach i {y x1 x2 speed} {unset game_shot_${i}($l)}
	    continue
	}
	
	.game.c coords $l $game_shot_x1($l) $game_shot_y($l) $game_shot_x2($l) $game_shot_y($l)
    }
}

proc game_random {n} {
    global game_rseed
    set game_rseed [expr {(($game_rseed * 13 + 67890) % 987613)}]
    return [expr {$game_rseed % $n}]
}

proc game_new_bubble {} {
    global game_width game_height game_bubbles game_nbubbles
    
    set x [game_random $game_width]
    set y [game_random $game_height]
    set bubble [.game.c create oval $x $y [expr {$x + 10}] [expr {$y + 10}] \
	      -outline blue -fill pink -width 2]
    set game_bubbles($bubble) 1
    incr game_nbubbles
}

proc game_update_bubbles {} {
    global game_bubbles game_xpos game_ypos game_shot_y game_shot_x1 game_shot_x2
    global game_nbubbles game_is_shot game_width game_height game_nbs
    
    foreach d [array names game_bubbles] {
	set coords [.game.c coords $d]
	foreach i {0 1 2 3} {
	    set [lindex {x1 y1 x2 y2} $i] [expr {int([lindex $coords $i])}]
	}
	set bb [.game.c bbox $d]
	set over [eval .game.c find overlapping $bb]
	set gone 0
	foreach o $over {
	    if [info exists game_is_shot($o)] {
		set gone 1
		break
	    }
	    foreach t [.game.c gettags $o] {
		if {$t == "ship_tag"} {
		    game_make_splat
		    set gone 1
		    break
		}
	    }
	    if $gone break
	}
	if $gone {
	    .game.c delete $d
	    unset game_bubbles($d)	    
	    incr game_nbubbles -1		    
	    incr game_nbs
	    .game.bubbles configure -text "   Bubbles shot: $game_nbs   "
	    continue
	}
	
	set dx [expr {[game_random 10] - 5}]
	set dy [expr {[game_random 10] - 5}]
	incr x1 $dx
	incr y1 $dy
	if {$x1 < 0} {set x1 0}
	if {$x1 > $game_width} {set x1 $game_width}
	if {$y1 < 0} {set y1 0}
	if {$y1 > $game_height} {set y1 $game_height}
	incr x2 [expr {$dx + [game_random 4] - 1}]
	incr y2 [expr {$dy + [game_random 4] - 1}]
	.game.c coords $d $x1 $y1 $x2 $y2
    }   
}

proc game {} {
    global game_width game_height game_xpos game_ypos game_xvel
    global game_dir game_thrust game_done game_nbubbles game_rseed
    global game_ships game_nbs game_bubbles game_shot_y
    global game_mousex game_mousey game_is_shot game_shot_y game_bubbles
    
    set game_width 800
    set game_height 600
    set game_xpos 300
    set game_ypos 200
    set game_xvel 0
    set game_dir 1
    set game_thrust 0
    set game_nbubbles 0
    set game_rseed 12345
    set game_ships 1
    set game_nbs 0
    catch {unset game_mousex}
    catch {unset game_mousey}
    catch {unset game_is_shot}
    catch {unset game_shot_y}
    catch {unset game_bubbles}

    catch {top_destroy .game}
    top_window .game
    label .game.top -text "Shoot the bubbles"
    label .game.top2 -text "Space = thrust, left = fire, right = change direction, mouse Y pos controls Y velocity"
    canvas .game.c -width $game_width -height $game_height -background black
    button .game.done -text "Quit" -command "set game_done 1"
    label .game.ships -text "  Ship number: $game_ships   "
    label .game.bubbles -text "   Bubbles shot: $game_nbs   "
    pack append .game \
	.game.top {top fill} \
	.game.top2 {top fill} \
	.game.c {top fill} \
	.game.done {left} \
	.game.ships {left} \
	.game.bubbles {left}
    
    bind .game.c <Any-KeyPress-space> {set game_thrust 1}
    bind .game.c <Any-KeyRelease-space> {set game_thrust 0}
    bind .game.c <ButtonPress-1> {game_new_shot}
    bind .game.c <ButtonPress-3> {if {$game_dir == 1} {set game_dir -1} else {set game_dir 1}}
    bind .game.c <Motion> {set game_mousex %x; set game_mousey %y}
    set f [focus]
    focus .game.c
    
    top_geometry .game +100+100
    
    set game_done 0
    while 1 {
	game_update
	if [info exists game_shot_y] game_shots
	if [info exists game_bubbles] game_update_bubbles
	if {$game_nbubbles < 5} game_new_bubble
	if $game_done {
	    top_destroy .game
	    focus $f
	    return
	}
    }
}

# game
