diff --git a/Engine.cc b/Engine.cc index d6dbdc6..cb196f5 100644 --- a/Engine.cc +++ b/Engine.cc @@ -985,7 +985,7 @@ Engine::Object::Object(bool is_static, OdeWorld & world, WFObj * obj, m_display_list = obj->render(); const float * obj_aabb = obj->getAABB(); for (int i = 0; i < 6; i++) - m_aabb[i] = obj_aabb[i]; + m_aabb[i] = scale * obj_aabb[i]; m_display_list_refcnt = new int; *m_display_list_refcnt = 1; m_is_visible = true; diff --git a/lib/demo/bowling.lua b/lib/demo/bowling.lua index ed69ec0..2c237ee 100644 --- a/lib/demo/bowling.lua +++ b/lib/demo/bowling.lua @@ -4,19 +4,20 @@ ag.import("std") function resetPins() local head_x = 0 local head_y = 15 - local spacing = 0.7 + local spacing = 0.75 for i = 1, 10 do if (pins[i] ~= nil) then pins[i]:destroy() end end local n = 1 - for row = 0, 4 do + for row = 0, 3 do for j = 0, row do pins[n] = reference_pin:clone() pins[n]:setPosition(head_x - row * spacing / 2 + j * spacing, head_y + 0.866 * spacing * row, 1 - pin_minz) + n = n + 1 end end end @@ -42,12 +43,12 @@ function setupScore() score = {} for i = 1, 10 do local s = {} - s[1] = 0 - s[2] = 0 - s["tot"] = 0 + s[1] = -1 + s[2] = -1 if (i == 10) then - s[3] = 0 + s[3] = -1 end + s["tot"] = -1 score[i] = s end end @@ -56,56 +57,73 @@ function init_event() lane = ag.loadModelStatic("bowling_lane") local minx, miny, minz, maxx, maxy, maxz = lane:getAABB() local lane_bottom = minz + local lane_top = maxz pins = {} reference_pin = ag.loadModel("bowling_pin", 1.0/4.3) minx, miny, minz, maxx, maxy, maxz = reference_pin:getAABB() pin_minz = minz pin_maxz = maxz + pin_standing_position = lane_top - pin_minz local box = ag.createBoxStatic(1, 10, 0.1) box:setVisible(false) box:setPosition(0, 0, lane_bottom - (maxz - minz) - 0.4) reference_pin:setPosition(0, 0, lane_bottom - maxz - 0.1) - reference_ball = ag.createSphere(0.3) + reference_ball = ag.createSphere(0.25) reference_ball:setColor(0.7, 0.1, 0.9) reference_ball:setMass(10) reference_ball:setPosition(0, -2, -1.5) - resetPins() setupStars() setupScore() position_x = 0 target_x = 0 game_state = "waiting" - last_update_time = ag.elapsedTime() mouse_moved = false - setCamera() + newFrame() + last_update_time = ag.elapsedTime() + setCamera(last_update_time) end -function setCamera() - ag.setCamera(position_x, -10, 5, target_x, 20, 0) +function setCamera(now) + if (game_state == "launched") then + local pct = (now - launch_time) / 2500 + if (pct > 1) then + pct = 1 + end + ag.setCamera(position_x + (-position_x * pct), -10 + 10 * pct, 5 + 5 * pct, target_x, 20, 0) + else + ag.setCamera(position_x, -10, 5, target_x, 20, 0) + end end function update_event() local now = ag.elapsedTime() - if (ag.isKeyDown("a") or ag.isKeyDown("left")) then - position_x = position_x - (now - last_update_time) / 300 - if (position_x < -2) then - position_x = -2 + if (game_state == "waiting") then + if (ag.isKeyDown("a") or ag.isKeyDown("left")) then + position_x = position_x - (now - last_update_time) / 300 + if (position_x < -2) then + position_x = -2 + end end - end - if (ag.isKeyDown("d") or ag.isKeyDown("right")) then - position_x = position_x + (now - last_update_time) / 300 - if (position_x > 2) then - position_x = 2 + if (ag.isKeyDown("d") or ag.isKeyDown("right")) then + position_x = position_x + (now - last_update_time) / 300 + if (position_x > 2) then + position_x = 2 + end end end last_update_time = now - setCamera() + if (game_state == "launched") then + if (now - launch_time > 7000) then + endBall() + end + end + setCamera(now) ag.callList(stars) end function mouse_motion_event(x, y, xrel, yrel) - if (mouse_moved) then + if (mouse_moved and game_state == "waiting") then target_x = target_x + xrel / 100 if (target_x < -2) then target_x = -2 @@ -136,11 +154,11 @@ function drawFrameScore(width, height, frame, fs) balls = 3 end for ball = 1, balls do - if ((frame < current_frame) or (frame == current_frame and ball < current_ball)) then + if (fs[ball] ~= -1) then local ball_base_x = base_x + local_width - (1 + balls - ball) * ball_size + 7 local ball_base_y = base_y + size - ball_size + 7 ag.drawText(fs[ball], 1, 0.6, 0, 14, ball_base_x, ball_base_y) - if (frame < current_frame and fs["tot"] ~= 0) then + if (fs["tot"] ~= -1) then local w, h = ag.getTextSize(fs["tot"], 16) ag.drawText(fs["tot"], 1, 0.6, 0, 16, base_x + local_width - 10 - w, base_y + 10) end @@ -163,6 +181,11 @@ function update_overlay_event(width, height) if (game_state == "get_accuracy" or game_state == "launched") then drawAccuracyBar(width, height) end + if (game_state == "waiting") then + local cursor_size = 8 + ag.drawLine(0, 1, 0, width / 2, height / 2 - cursor_size, width / 2, height / 2 + cursor_size) + ag.drawLine(0, 1, 0, width / 2 - cursor_size, height / 2, width / 2 + cursor_size, height / 2) + end end function mousebutton_down_event(button, x, y) @@ -195,17 +218,117 @@ function launchBall() game_state = "launched" launch_time = ag.elapsedTime() bowling_ball = reference_ball:clone() - bowling_ball:setPosition(position_x, -10, 1.31) + bowling_ball:setPosition(position_x, -10, 1.26) local fx = target_x + accuracy - position_x local fy = 30 -- should match setCamera()'s dy local d = math.sqrt(fx*fx + fy*fy) fx = fx / d fy = fy / d - local force = 200000 + local force = 150000 force = force * 0.5 + force * 0.5 * power bowling_ball:addForce(fx * force, fy * force, 0) end +function endBall() + game_state = "waiting" + bowling_ball:destroy() + -- find all the pins that were knocked over + local pin_count = 0 + for i = 1, 10 do + if (pins[i] ~= nil) then + local x, y, z = pins[i]:getPosition() + if (z < pin_standing_position - 0.05) then + pins[i]:destroy() + pins[i] = nil + pin_count = pin_count + 1 + end + end + end + updateScore(pin_count) +end + +function getNextBall(frame, ball) + ball = ball + 1 + if (ball > 2 and frame < 10) then + frame = frame + 1 + ball = 1 + end + return frame, ball +end + +function getNextBallAfterStrike(frame, ball) + if (frame == 10) then + ball = ball + 1 + else + frame = frame + 1 + end + return frame, ball +end + +function updateScore(pin_count) + score[current_frame][current_ball] = pin_count + -- update total score + for f = 1, 10 do + local prevscore = 0 + if (f > 1) then + prevscore = score[f-1]["tot"] + end + if (score[f][1] == 10) then -- strike + local nf, nb = getNextBallAfterStrike(f, 1) + if (score[nf][nb] == -1) then + break + else + local nf2, nb2 + if (score[nf][nb] == 10) then + nf2, nb2 = getNextBallAfterStrike(nf, nb) + else + nf2, nb2 = getNextBall(nf, nb) + end + if (score[nf2][nb2] == -1) then + break + else + score[f]["tot"] = prevscore + 10 + score[nf][nb] + score[nf2][nb2] + end + end + elseif (score[f][1] == -1 or score[f][2] == -1) then + break + elseif (score[f][1] + score[f][2] == 10) then -- spare + if (score[f+1][1] == -1) then + break + else + score[f]["tot"] = prevscore + 10 + score[f+1][1] + end + else + score[f]["tot"] = score[f][1] + score[f][2] + end + end + if (pin_count == 10 and current_frame < 10) then + current_frame = current_frame + 1 + current_ball = 1 + newFrame() + elseif (current_frame == 10) then + current_ball = current_ball + 1 + if ((current_ball == 3 and (score[10][1] + score[10][2]) < 10) or (current_ball == 4)) then + gameOver() + end + else + current_ball = current_ball + 1 + if (current_ball > 2) then + current_ball = 1 + current_frame = current_frame + 1 + newFrame() + end + end +end + +function newFrame() + resetPins() +end + +function gameOver() + game_state = "gameover" +end + function drawPowerBar(width, height) local bar_width = 80 local bar_height = 400