The main unit of the web version of Invader
by Steven Binns: Y11 Age ~15 converted to run in Smart Mobile Studio by PPS
Introduction
The conversion of the code to run in Smart Mobile Studio was fairly straightforward, with much of the code surviving unchanged. Note that our alpha component of the colour has a maximum of 1 whereas in SDL it is 255.
The conversion demonstrates:
- input from the mouse and keyboard;
- the display of text with Canvas.FillTextF and circles with Canvas.ArcF;
- alpha blending;
- audio.
The Code
unit InvaderJS; { Copyright (c) 2011 Steven Binns Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License, as described at http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/ Converted to run in Smart Mobile Studio by PPS (2013) } interface uses W3System, W3Components, W3Application, W3Game, W3GameApp, W3Graphics, W3MediaElements, Globals, enemies; type TApplication = class(TW3CustomGameApplication) private FAudioElement: TW3AudioElement; level, mousex, mousey : integer; timer : integer; scoretext : string; font : string; colour, colour2 : string; spawn : Boolean = false; protected procedure ApplicationStarting; override; procedure ApplicationClosing; override; procedure PaintView(Canvas: TW3Canvas); override; procedure KeyDownEvent(mCode:integer); end; implementation procedure TApplication.KeyDownEvent(mCode:integer); begin if mCode=27 then Application.Terminate; end; procedure TApplication.ApplicationStarting; begin inherited; GameView.Delay := 20; GameView.Width := 400; GameView.Height := 400; asm window.onkeydown=function(e) { TApplication.KeyDownEvent(Self,e.keyCode); } end; KeyDownEvent(0); GameView.OnMouseDown := procedure(o : TObject; b : TMouseButton; t : TShiftState; x, y : integer) begin mousex := x; mousey := y; end; GameView.OnMouseMove := procedure (o : TObject; t : TShiftState; x, y : Integer) begin mousex := x; mousey := y; end; colour := 'green'; colour2 := 'black'; tick := 0; score := 1; font := '16pt Arial'; level := 5; timer := (level * 300) + 5000; FAudioElement := TW3AudioElement.Create; FAudioElement.AutoPlay := False; FAudioElement.Loop := True; if FAudioElement.CanPlayTypeAsBoolean('audio/mpeg') then begin FAudioElement.Source := 'John Stump - Death Waltz.mp3'; FAudioElement.Play; end; GameView.StartSession(True); end; procedure TApplication.ApplicationClosing; begin FAudioElement.Pause; GameView.EndSession; inherited; end; procedure TApplication.PaintView(Canvas: TW3Canvas); procedure Draw_Enemies(level: integer); var i : integer; begin for i := 0 to 20 do begin if mobs[i, 0] = 1 then //if the enemy exists begin //draw the enemy body Canvas.FillStyle := 'rgba(0, 255, 0, 0.5)'; Canvas.StrokeStyle := 'rgba(0, 255, 0, 0.5)'; Canvas.BeginPath; Canvas.ArcF(mobsx[i], mobsy[i], mobs[i, 3] DIV 2, 0, PI * 2, true); Canvas.ClosePath; Canvas.Stroke; Canvas.Fill; if mobs[i, 4] = 0 then //if the enemy isn't chasing you begin //draw a white aggro circle Canvas.FillStyle := 'rgba(255, 255, 255, 0.5)'; Canvas.StrokeStyle := 'rgba(255, 255, 255, 0.5)'; Canvas.BeginPath; Canvas.ArcF(mobsx[i], mobsy[i], mobs[i, 3], 0, PI * 2, true); Canvas.ClosePath; Canvas.Stroke; Canvas.Fill; end else if mobs[i, 4] = 1 then //if the enemy is chasing you begin //draw a red aggro circle Canvas.FillStyle := 'rgba(150, 0, 0, 0.5)'; Canvas.StrokeStyle := 'rgba(150, 0, 0, 0.5)'; Canvas.BeginPath; Canvas.ArcF(mobsx[i], mobsy[i], mobs[i, 3], 0, PI * 2, true); Canvas.ClosePath; Canvas.Stroke; Canvas.Fill; end; if tick = 10 then //Increase the score by the combined radii of all the enemies chasing you (divided by 10). score := score + mobs[i, 3] DIV 10; end; end; end; begin if timer = (level * 300) + 4000 then spawn := true; // Clear background Canvas.FillStyle := 'rgb(0, 0, 0)'; Canvas.FillRectF(0, 0, GameView.Width, GameView.Height); scoretext := 'SCORE: ' + inttostr(score); // Draw score on the screen Canvas.Font := font; Canvas.FillStyle := colour; Canvas.FillTextF(scoretext, 10, 20, MAX_INT); if timer = 0 then begin level := level + 5; timer := (level * 300) + 5000; //after the timer runs out, advance the level end; enemies.Tick_Enemies(mousex, mousey); //draw the character Canvas.FillStyle := 'rgba(255, 99, 0, 0.5)';//reddish Canvas.StrokeStyle := 'rgba(255, 99, 0, 0.5)'; Canvas.BeginPath; Canvas.ArcF(mouseX, mouseY, level, 0, PI * 2, true); Canvas.ClosePath; Canvas.Stroke; Canvas.Fill; Canvas.FillStyle := 'rgba(0, 0, 255, 0.5)'; //blue Canvas.StrokeStyle := 'rgba(0, 0, 255, 0.5)'; Canvas.BeginPath; Canvas.ArcF(mouseX, mouseY, level div 5, 0, PI * 2, true); Canvas.ClosePath; Canvas.Stroke; Canvas.Fill; //draw enemies Draw_Enemies(level); if spawn = true then begin if 100 * random < 10 then enemies.Create_Enemy(level); //Check collisions between enemies and the character. checks.Check_Collisions(level, mousex, mousey); end; inc(tick); if tick = 10 then begin inc(score); tick := 0; end; timer := timer - 10; if stop then begin Canvas.FillStyle := 'red'; scoretext := 'SCORE: ' + inttostr(score); Canvas.FillTextF(scoretext, 10, 20, MAX_INT); Canvas.FillTextF('You were assimilated...', 20, 200, MAX_INT); Canvas.FillTextF('Reload (F5) for another game', 20, 300, MAX_INT); if FAudioElement.CanPlayTypeAsBoolean('audio/mpeg') then FAudioElement.Pause; GameView.EndSession; end; end; end.