-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathspaceshipcontroller.lua
401 lines (320 loc) · 13.4 KB
/
spaceshipcontroller.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
dofile("spacelib.lua")
--[[
API:
AddSprite(string texturePath, Vec2 position, number rotation, Vec2 size) -> integer:
- Create a new sprite using `texturePath` (if not empty) at `position` with an angle (in degrees) of `rotation` and a size of `size`
Returns the sprite id which can be used to update any of the sprite properties at any time
If an empty texturePath is given, the sprite will be a white rectangle (which you can call UpdateSpriteColor upon)
ClearSprites()
- Clear/destroy every sprite, making every sprite id returned previously by AddSprite invalid
This is automatically done when a script is reloaded
DeleteSprite(integer id)
- Destroy the sprite of id `id`
GetScreenSize() -> table(width, height)
- Return the application window size
GetSpaceshipName() -> string
- Returns player controlled spaceship name
GetSpaceshipPosition() -> table(x, y, z)
- Returns player controlled spaceship physical position
GetSpaceshipRotation() -> table(w, x, y, z)
- Returns player controlled spaceship physical rotation
GetSpaceshipAngularVelocity() -> table(x, y, z)
- Returns player controlled spaceship angular velocity
GetSpaceshipLinearVelocity() -> table(x, y, z)
- Returns player controlled spaceship linear velocity
IsChatboxActive() -> boolean
- Returns whether the chatbox is active (currently used for typing) or not
PrintChatbox(string text)
- Print something to the chat (which only the local player can see)
Project(Vec3 worldPosition) -> table(x, y)
- Returns the screen position corresponding to a world-space position (can be out of screenspace)
RecenterMouse()
- Center the mouse at the center of the window, whether it is visible or not
ScanEntities() -> table(complex)
- Scan the world and returns every entity in a table
[unique_id] = {
["type"] = one of "spaceship", "projectile", "ball" and "earth"
["name"] = name of the entity, empty for projectiles
["position"] = table(x, y, z)
["rotation"] = table(x, y, z)
["angularVelocity"] = table(x, y, z)
["linearVelocity"] = table(x, y, z)
}
This function is heavy, do not call it often
Shoot()
- Shoot a projectile (if possible) from the player spaceship
ShowCursor(boolean show)
- Show/hide the system mouse
ShowHealthbar(boolean show)
- Show/hide the application's default healthbar, allowing you to make your own (using event OnIntegrityUpdate)
ShowSprite(integer id)
- Show/hide a sprite by id, `id` must be valid
UpdateCamera(Vec3 position, Quaternion rotation)
- Sets the camera to a particular position and rotation, in worldspace.
The camera is not attached to the spaceship, this function can be used to do it.
Currently, the camera is not restricted and can move anywhere, this is intended but not a definitive behaviour
UpdateSpriteColor(integer id, table color)
- Changes the color (alpha included) of a sprite by id, `id` must be valid, `color` must contains at least fields "r", "g" and "b" (with a value between 0 and 255)
You can also set a field "a" to set the new alpha value of the sprite.
You can use the utility Color function to easily create a color tabl.
UpdateSpritePosition(integer id, Vec2 position, number rotation)
- Changes the position and rotation of a sprite by id, `id` must be valid, `rotation` is in degrees.
UpdateSpriteSize(integer id, Vec2 size)
- Changes the size of a sprite by id, `id` must be valid.
Events:
Events are Lua function called when something happens in the world, implementing them is not mandatory (with the exception of UpdateInput)
Be warned that, due to technical reasons (and a bit of laziness), vectors and quaternions values parameters are NOT compatible with Vec2, Vec3 and Quaternion from spacelib.lua
You have to recreate a valid Vec2/Vec3/Quaternion to use them correctly.
Init()
- Called just after the (re)loading of the Lua script.
Be warned that everything is lost when a script is reloaded, as every variables from the previous script will be destroyed.
OnBotError(string error)
- Called when player bot crashed, with `error` being the Lua script error
OnBotWarning(string warning)
- Called when player bot script called warn function, with warning message
OnBotMessage(string msg)
- Called when player bot script called notice or print function, with message
OnKeyPressed(table event)
- Called when a key is pressed/repeated
Fields:
- string key: key name
- boolean alt: Was an Alt key pressed when the key was pressed
- boolean control: Was a Control key pressed when the key was pressed
- boolean repeated: Is this event generated by a repetition or not
- boolean shift: Was a Shift key pressed when the key was pressed
- boolean system: Was a System key pressed when the key was pressed
OnKeyReleased(table event)
- Called when a key is released
Uses the same fields as the OnKeyPressed event
OnLostFocus()
- Called when the window loses focus, use this event to clear any key state to prevent troubles
OnIntegrityUpdate(number integrity)
- Called when your spaceship integrity values changes (currently only fired when you get hit or respawn)
OnMouseButtonPressed(table event)
- Called when a mouse button is pressed
Fields:
- string button: button name
- integer x: X part of the mouse global position when the button was pressed
- integer y: Y part of the mouse global position when the button was pressed
OnMouseButtonReleased(table event)
- Called when a mouse button is pressed
Uses the same fields as the OnMouseButtonPressed event
OnMouseMoved(table event)
- Called when the mouse moved (whether it is visible or not)
Fields:
- integer x: X part of the mouse global position
- integer y: Y part of the mouse global position
- integer deltaX: X part of the mouse relative movement since the last event
- integer deltaY: Y part of the mouse relative movement since the last event
OnUpdate(table(x, y, z) position, table(w, x, y, z) rotation, number elapsedTime)
- Called every frame with the current position and rotation of the player's spaceship.
Keep this function lightweight to preserve performances
OnWindowSizeChanged(table size)
- Called when the window gets resized
Fields:
- integer width: Window new width
- integer height: Window new height
UpdateInput(number elapsedTime) -> Vec3, Vec3
- Called every 60th of a second to gets the ship new inputs
Must returns two variables:
- Vec3 acceleration: Ship new acceleration in local space
- Vec3 torque: Ship new torque in global space
]]
-- Constants
local Acceleration = 1.0 -- 100%
local AscensionSpeed = 0.66 -- 66%
local DistMax = 200
local RollSpeed = 0.66 -- 66%
local RotationSpeedPerPixel = 0.002 -- 0.2%
local StrafeSpeed = 0.66 -- 66%
-- Work vars
local CrosshairSprite
local DamageSprite
local DamageAlpha = 0
local FreeFlightCamAngles = Vec3.New()
local FreeFlightCamPos = Vec3.New()
local FreeFlightCamRot = Quaternion.New()
local KeyPressed = {}
local IsRotationEnabled = false
local IsFreeFlightEnabled = false
local MovementSprite
local MouseButtonPressed = {}
local RotationCursorPosition = Vec2.New(0, 0)
local ScreenSize
local SynchronizeCamera = false
function Init()
OnWindowSizeChanged(GetScreenSize())
CrosshairSprite = AddSprite("Assets/weapons/crosshair.png", Vec2.New(0, 0), 0, Vec2.New(32, 32))
DamageSprite = AddSprite("", ScreenSize * 0.5, 0, ScreenSize)
MovementSprite = AddSprite("Assets/cursor/orientation.png", Vec2.New(0, 0), 0, Vec2.New(32, 32))
ShowSprite(DamageSprite, false)
ShowSprite(MovementSprite, false)
end
function OnKeyPressed(event)
if (IsChatboxActive()) then
return
end
if (event.key == "Space") then
Shoot()
elseif (event.key == "Tab") then
IsFreeFlightEnabled = not IsFreeFlightEnabled
if (IsFreeFlightEnabled) then
ShowCursor(false)
ShowSprite(MovementSprite, false)
SynchronizeCamera = true
PrintChatbox("Freeflight camera enabled")
else
ShowCursor(true)
PrintChatbox("Freeflight camera disabled")
end
else
KeyPressed[event.key] = true
end
end
function OnKeyReleased(event)
KeyPressed[event.key] = false
end
function OnLostFocus()
KeyPressed = {}
MouseButtonPressed = {}
end
function OnIntegrityUpdate(health)
DamageAlpha = 100
UpdateSpriteColor(DamageSprite, Color(255, 0, 0, DamageAlpha))
ShowSprite(DamageSprite, true)
end
function OnMouseButtonPressed(event)
MouseButtonPressed[event.button] = true
if (event.button == "Right" and not IsFreeFlightEnabled) then
ShowCursor(false)
IsRotationEnabled = true
RotationCursorPosition = Vec2.New(0, 0)
ShowSprite(MovementSprite, true)
UpdateSpriteColor(MovementSprite, Color(255, 255, 255, 0))
end
end
function OnMouseButtonReleased(event)
MouseButtonPressed[event.button] = false
if (event.button == "Right" and not IsFreeFlightEnabled) then
ShowCursor(true)
IsRotationEnabled = false
RotationCursorPosition = Vec2.New(0, 0)
ShowSprite(MovementSprite, false)
end
end
function OnMouseMoved(event)
if (IsFreeFlightEnabled) then
local sensitivity = 0.3
FreeFlightCamAngles.x = Clamp(FreeFlightCamAngles.x - event.deltaY * sensitivity, -89, 89)
FreeFlightCamAngles.y = math.fmod(FreeFlightCamAngles.y - event.deltaX * sensitivity, 360)
FreeFlightCamRot = Quaternion.FromEulerAngles(FreeFlightCamAngles.x, FreeFlightCamAngles.y, FreeFlightCamAngles.z)
RecenterMouse()
return
end
if (not IsRotationEnabled) then
return
end
RotationCursorPosition.x = RotationCursorPosition.x + event.deltaX
RotationCursorPosition.y = RotationCursorPosition.y + event.deltaY
if (RotationCursorPosition:SquaredLength() > DistMax * DistMax) then
RotationCursorPosition:Normalize()
RotationCursorPosition = RotationCursorPosition * DistMax
end
local cursorAngle = math.deg(math.atan(RotationCursorPosition.y, RotationCursorPosition.x))
local cursorAlpha = RotationCursorPosition:SquaredLength() / (DistMax * DistMax)
UpdateSpritePosition(MovementSprite, ScreenSize * 0.5 + RotationCursorPosition, cursorAngle)
UpdateSpriteColor(MovementSprite, Color(255, 255, 255, math.floor(cursorAlpha * 255)))
RecenterMouse()
end
function OnUpdate(visualPosition, visualRotation, elapsedTime)
setmetatable(visualPosition, Vec3)
setmetatable(visualRotation, Quaternion)
if (IsFreeFlightEnabled) then
if (SynchronizeCamera) then
FreeFlightCamPos = visualPosition + visualRotation * (Vec3.Backward * 12.0 + Vec3.Up * 5)
FreeFlightCamRot = visualRotation * Quaternion.FromEulerAngles(-10, 0.0, 0.0)
FreeFlightCamAngles = FreeFlightCamRot:ToEulerAngles()
FreeFlightCamAngles.z = 0 -- cancel roll
SynchronizeCamera = false
end
UpdateCamera(FreeFlightCamPos, FreeFlightCamRot)
else
UpdateCamera(visualPosition + visualRotation * (Vec3.Backward * 12.0 + Vec3.Up * 5), visualRotation * Quaternion.FromEulerAngles(-10, 0.0, 0.0))
end
local targetPos = visualPosition + visualRotation * (Vec3.Forward * 150)
UpdateSpritePosition(CrosshairSprite, Project(targetPos), 0)
end
function OnWindowSizeChanged(size)
ScreenSize = Vec2.New(size.width, size.height)
if (DamageSprite) then
UpdateSpritePosition(DamageSprite, ScreenSize * 0.5, 0)
UpdateSpriteSize(DamageSprite, ScreenSize)
end
end
function UpdateInput(elapsedTime)
if (KeyPressed["G"] or (MouseButtonPressed["Left"] and IsRotationEnabled)) then
Shoot()
end
local SpaceshipMovement = Vec3.New()
local SpaceshipRotation = Vec3.New()
if (KeyPressed["Z"]) then
SpaceshipMovement = SpaceshipMovement + Vec3.Forward * Acceleration
end
if (KeyPressed["S"]) then
SpaceshipMovement = SpaceshipMovement - Vec3.Forward * Acceleration
end
local leftSpeedModifier = 0.0
if (KeyPressed["Q"]) then
SpaceshipMovement = SpaceshipMovement + Vec3.Left * Acceleration
end
if (KeyPressed["D"]) then
SpaceshipMovement = SpaceshipMovement + Vec3.Right * Acceleration
end
local AscensionSpeedModifier = 0.0
if (KeyPressed["LShift"]) then
SpaceshipMovement = SpaceshipMovement + Vec3.Up * Acceleration
end
if (KeyPressed["LControl"]) then
SpaceshipMovement = SpaceshipMovement + Vec3.Down * Acceleration
end
local rollSpeedModifier = 0.0
if (KeyPressed["A"]) then
SpaceshipRotation.z = SpaceshipRotation.z + RollSpeed
end
if (KeyPressed["E"]) then
SpaceshipRotation.z = SpaceshipRotation.z - RollSpeed
end
local rotationDirection = RotationCursorPosition
SpaceshipRotation.x = Clamp(-rotationDirection.y * RotationSpeedPerPixel, -1.0, 1.0)
SpaceshipRotation.y = Clamp(-rotationDirection.x * RotationSpeedPerPixel, -1.0, 1.0)
-- This should be in OnUpdate function
if (DamageAlpha > 0) then
DamageAlpha = DamageAlpha - elapsedTime * 200
if (DamageAlpha < 0) then
ShowSprite(DamageSprite, false)
else
UpdateSpriteColor(DamageSprite, Color(255, 0, 0, math.floor(DamageAlpha)))
end
end
if (IsFreeFlightEnabled) then
FreeFlightCamPos = FreeFlightCamPos + FreeFlightCamRot * Vec3.New(-SpaceshipMovement.y, SpaceshipMovement.z, -SpaceshipMovement.x)
return Vec3.New(), Vec3.New()
else
-- Make rotation global
local orientation = GetSpaceshipRotation()
setmetatable(orientation, Quaternion)
SpaceshipRotation = orientation * SpaceshipRotation
return SpaceshipMovement, SpaceshipRotation
end
end
function OnBotError(errMessage)
PrintChatbox("Our bot just crashed")
print("Bot error message: " .. errMessage)
end
function OnBotWarning(errMessage)
PrintChatbox("Our bot sent us a warning")
print("Bot warning: " .. errMessage)
end
function OnBotMessage(errMessage)
print("Bot message: " .. errMessage)
end