Body: Store the previous position every time the position is set.
[scd.git] / src / net / habraun / sd / Body.scala
blobc6e79e00ea6a881d6a5fedef9c55e6d59b9f7491
1 /*
2 Copyright (c) 2009 Hanno Braun <hanno@habraun.net>
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
19 package net.habraun.sd
23 import collision._
24 import math._
28 /**
29 * Models a rigid body.
30 * Body is mostly a data structure with very little logic. It needs to be added to a world in order to do
31 * anything useful.
34 class Body {
36 /**
37 * The body's position in the world, measured in meters.
38 * After creation, a body has an initial position of (0, 0).
39 * Must not be null.
42 private[this] var _position = Vec2D(0, 0)
44 def position = _position
46 def position_=(p: Vec2D) {
47 if (p == null) throw new NullPointerException
48 _previousPosition = _position
49 _position = p
54 /**
55 * The previous position of the body, before the position was set.
56 * This attribute is initialized with the value Vec2D(0, 0).
59 private[this] var _previousPosition = Vec2D(0, 0)
61 def previousPosition = _previousPosition
65 /**
66 * The body's shape.
67 * The shape is needed for collision detection.
68 * Must not be null.
71 private[this] var _shape: Shape = NoShape
73 def shape = _shape
75 def shape_=(s: Shape) {
76 if (s == null) throw new NullPointerException
77 _shape = s
82 /**
83 * The body's velocity, measured in meters per second.
84 * Velocity vectors with a size greater than the maximum velocity will be shortened, retaining their
85 * direction.
86 * After creation, a body has an initial velocity of (0, 0).
87 * Must not be null.
90 private[this] var _velocity = Vec2D(0, 0)
92 def velocity = _velocity
94 def velocity_=(v: Vec2D) {
95 if (v == null) throw new NullPointerException
97 // Check if the new velocity is greater than the maximum velocity.
98 if (v * v > maxVelocity * maxVelocity) {
99 // It is. Set the velocity to the maximum velocity while retaining the direction of the new
100 // velocity.
101 _velocity = v * (maxVelocity / Math.sqrt(v * v))
103 else {
104 // It is not, which means we can safely set the velocity to the new velocity.
105 _velocity = v
112 * The body's mass, measured in kilograms.
113 * After creation, a body has an initial mass of 1. The mass must never be negative or zero.
114 * A mass of Double.PositiveInfinity indicates that a body is static. Static bodies don't move. Forces
115 * have no effect on them.
118 private[this] var _mass = 1.0
120 def mass = _mass
122 def mass_=(m: Double) {
123 if (m <= 0) throw new IllegalArgumentException
124 _mass = m
130 * Applies a force to the body.
131 * The effect of applied forces is computed when the world simulation is stepped.
132 * Calling this method several times between steps will simply add the applied forces up. When the
133 * simulation is stepped, the sum of all the forces is applied.
134 * A force must never be null.
137 private[this] var _appliedForce = Vec2D(0, 0)
139 def appliedForce = _appliedForce
141 def applyForce(f: Vec2D) {
142 _appliedForce += f
145 def resetForce {
146 _appliedForce = Vec2D(0, 0)
152 * Applies an impulse to the body.
153 * The effect of the impulse is computed when the world simulation is stepped.
154 * Valling this method several times between steps will simply add the applied impulses up. When the
155 * simulation is stepped, the sum of all the impulses is applied.
156 * An impulse must never be null.
159 private[this] var _appliedImpulse = Vec2D(0, 0)
161 def appliedImpulse = _appliedImpulse
163 def applyImpulse(impulse: Vec2D) {
164 _appliedImpulse += impulse
167 def resetImpulse {
168 _appliedImpulse = Vec2D(0, 0)
174 * Sets the maximum velocity for this body.
175 * After creation, a body has a maximum velocity of Double.PositiveInfinity.
176 * The maximum velocity must never be negative.
179 private[this] var _maxVelocity = Double.PositiveInfinity
181 def maxVelocity = _maxVelocity
183 def maxVelocity_=(mv: Double) {
184 if (mv < 0) throw new IllegalArgumentException
185 _maxVelocity = mv
191 * The movement of an object can be constrained. Currently it is only possible to disallow movement along
192 * the x and y axes.
195 private[this] var _xMovementAllowed = true
196 private[this] var _yMovementAllowed = true
198 def xMovementAllowed = _xMovementAllowed
200 def yMovementAllowed = _yMovementAllowed
202 def allowXMovement(allowed: Boolean) = _xMovementAllowed = allowed
204 def allowYMovement(allowed: Boolean) = _yMovementAllowed = allowed