Rendering Images
The demo enables you to move or spin the image by careful use of the mouse or touch. The image is George Wright's GroundEnemy.png from TowerOfArcher. We keep the code short by using only a single body. Gravity is zero, so the image is stationary initially. Box2D calculates the position and orientation of the bounding rectangle and using this data we draw the TW3Image in the same way as for a canvas project without a physics engine.
Demonstration
If you do not see the demonstration, your school security system might have blocked it. Click here to try it on a separate page.
Smart Pascal Code
This code compiles with Versions 3.0 (with warnings) and 2.2 of Smart Mobile Studio.
unit Unit1; interface uses System.Types, SmartCL.System, SmartCL.Components, SmartCL.Controls, SmartCL.Application, SmartCL.Game, SmartCL.GameApp, SmartCL.Graphics, SmartCL.MouseTouch, SmartCL.Touch, Box2DWrapper, SmartCL.Controls.Image; type TCanvasProject = class(TW3CustomGameApplication) private const FRAME_RATE = 1 / 60; const SCALE = 10; FWorld: Tb2World; FMousePos: Tb2Vec2; FIsMouseDown: Boolean; FMouseJoint: Tb2MouseJoint; FBody: Tb2Body; FImage: TW3Image; protected procedure ApplicationStarting; override; procedure ApplicationClosing; override; procedure PaintView(Canvas: TW3Canvas); override; procedure MouseDownHandler(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure MouseMoveHandler(Sender: TObject; Shift: TShiftState; X, Y: Integer); end; implementation procedure TCanvasProject.ApplicationStarting; var FixtureDef: Tb2FixtureDef; BodyDef: Tb2BodyDef; begin inherited; FWorld := Tb2World.Create( Tb2Vec2.Create(0.0, 0.0), // zero gravity True // allow sleep ); // Create fixture definition (used to describe fixture objects) FixtureDef := Tb2FixtureDef.Create; FixtureDef.Density := 1.0; BodyDef := Tb2BodyDef.Create; FixtureDef.Shape := Tb2PolygonShape.Create; // Create a rectangular dynamic object. BodyDef.BodyType := btDynamicBody; FMousePos := Tb2Vec2.Create(0, 0); GameView.OnMouseTouchClick := MouseDownHandler; GameView.OnMouseTouchRelease := lambda FIsMouseDown := False; end; GameView.OnMouseMove := MouseMoveHandler; GameView.OnTouchMove := lambda(sender: TObject; td: TW3TouchData) FMousePos.SetXY( td.Touches.Touches[0].PageX / SCALE, td.Touches.Touches[0].PageY / SCALE); end; FImage := TW3Image.Create(nil); FImage.LoadFromURL('res/GroundEnemy.png'); FImage.OnLoad := procedure(o : TObject) begin Tb2PolygonShape(FixtureDef.Shape).SetAsBox(0.5 * FImage.Width / SCALE, 0.5 * FImage.Height / SCALE); BodyDef.Position.SetXY(0.5 * GameView.Width / SCALE, 0.5 * GameView.Height / SCALE); FBody := FWorld.CreateBody(BodyDef); FBody.CreateFixture(FixtureDef); GameView.Delay := 5; GameView.StartSession(False); end; end; procedure TCanvasProject.ApplicationClosing; begin GameView.EndSession; inherited; end; procedure TCanvasProject.PaintView(Canvas: TW3Canvas); var MouseJointDef: Tb2MouseJointDef; begin // Draw background Canvas.FillStyle := 'rgb(20, 20, 50)'; Canvas.FillRectF(0, 0, GameView.Width , GameView.Height); // Handle mouse if FIsMouseDown and not Assigned(FMouseJoint) then begin MouseJointDef := Tb2MouseJointDef.Create; MouseJointDef.BodyA := FWorld.GetGroundBody; MouseJointDef.BodyB := FBody; MouseJointDef.Target.SetXY(FMousePos.X, FMousePos.Y); MouseJointDef.CollideConnected := True; MouseJointDef.MaxForce := 300.0 * FBody.GetMass; FMouseJoint := Tb2MouseJoint(FWorld.CreateJoint(MouseJointDef)); FBody.SetAwake(True); end; if Assigned(FMouseJoint) then if FIsMouseDown then FMouseJoint.SetTarget(FMousePos) else begin FWorld.DestroyJoint(FMouseJoint); FMouseJoint := nil; end; // Advance and draw world FWorld.Advance(FRAME_RATE, 6, 2); if Assigned(FBody) then begin var Pos := FBody.GetPosition; var Theta := FBody.GetAngle; Canvas.Save; Canvas.Translate(Pos.X * SCALE, Pos.Y * SCALE); Canvas.Rotate(Theta); Canvas.DrawImageF(FImage.Handle, -FImage.Width / 2, -FImage.Height / 2); Canvas.Restore; end; FWorld.ClearForces; end; procedure TCanvasProject.MouseDownHandler(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin FMousePos.SetXY(X / SCALE, Y / SCALE); FIsMouseDown := True; end; procedure TCanvasProject.MouseMoveHandler(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin FMousePos.SetXY(X / SCALE, Y / SCALE); end; end.