Quantcast

Jump to content

» «
Photo

Rotating objects 2

11 replies to this topic
Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#1

Posted 06 December 2005 - 12:37 AM

First, readthis.

Right, I thought of this possibly nearly a year ago, but never posted it cos I could never be bothered to write a full tutorial, I still can't but I'm going to shove the basics in your face.

It is an update to my rotating objects topic, there were limitations with it meaning you could only rotate on one axis, or another with VERY limited options.

Then, about a week later, I found this OpCode (it is, as guessed there set_object_rotation), and the code suddenly became alot better.

Basically you do what I did for one axis in the original thread for ALL the axies with this new one (or which ever ones you want to rotate on). You don't even need to rotate fully, you could just make it bob up and down while rotating or do any one of a number of things.

I was very keen to make a fairground mod where all the rides (I thought up lots to code, some pretty good (including a rollercoaster with full physics - could be good for Myriad, especially with the new island to fill)) but I could never get a modeller onto it enough to get models.

But yeah, I had loads of code snippetsfor it doing odd things, but I'm not sure where they are atm, or even if they're on this laptop.

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#2

Posted 08 December 2005 - 06:04 PM

Right, I'm sat in a programming lab supposed to be writing a java code framework from a UML diagram, that's not happening so I decided to update this as no-one seems to have paid it any attention. Note: as I am at uni atm, there are no images to demostrate it. I will then include some example code at the end (note again: as I am in uni I have no code on me so it will all be untested but should work, I can still remember what I did).

Basic Principles.

When you use "0400: $x $y $z get_point_on_object_plane $object offset $xoffset $yoffset $zoffset" the co-ordinate generated is RELATIVE to the original object POSITION AND ANGLE. So an offset of 5.0 0.0 0.0 will create a co-ordinate 5.0 DIRECTLY AHEAD of the object, not 5.0 along the x-axis from it.

Therefore if your object is rotating and you create an offset straight in front of it, it will be positioned at some point along a circle, radius offset, centre original object. This was how the old version worked in 2D using some OpCodes, this version has been updated to use better ones.

Basic Code.

CODE
004F: create_thread ££rotate000


CODE
:rotate000
03A4: name_thread "rotate" // OK, I had to look this line up
0247: request_model #waterjump // Find your own model to use
0247: request_model #uzi // Lets make a gun the centre (best to use an invisible model but I don't have one)
038B: load_requested_models // I'm disturbed that I've coded up to here purely from memory

:rotate001
0001: wait 10 ms
00D6: if 1
0248:   model #waterjump loaded
0248:   model #uzi loaded
004D: jump_if_false ££rotate001
0107: $centreobj = create_model #uzi at 100.3 420.6 12.6 // Can't guarantee the co-ordinates are good
0107: $rotateme = create_model #waterjump at 0.0 0.0 0.0
0249: release_model #uzi
0249: release_model #waterjump
0005: $zrot = 0.0

:rotate002:
0001: wait 50 ms // This is the start of the main control loop.  The delay here helps set speed.
0453: set_object $centreobj rotation 0.0 0.0 $zrot
0400: $x $y $z get_point_on_object_plane $centreobj offset 10.0 0.0 0.0
01BC: put_object $rotateme at $x $y $x
0086: $nurot = $zrot
0009: $nurot += 90.0
0177: set_object $ rotateme rotation $nurot
0009: $xrot += 10 // This angle will also help determine speed and granuality
00D6: if 0
0030:   $zrot > 360.0
004D: jump_if_false ££rotate002
000D: $zrot -= 360.0
0002: jump ££rotate002


Thats just a basic code to move a waterjump round in a basic circle, facing in the direction of travel (thats what the $nurot part did). There are obviously improvements that could be made to the code, not using globals everywhere, using less variables etc but that is a basic code. It also at the end limits $xrot so it stays within standard degrees.

You can also change the 3D point on the plane you are getting the co-ordinates from, so a line of:

CODE
0400: $x $y $z get_point_on_object_plane $centreobj offset 10.0 0.0 5.0


Will set the waterjump onto a circle 5.0 units above the centre object with still the same radius. If you changed the other angles you will get some wierd effects if you use them together. If you just want to make something rotate vertically like a ferris wheel, just alter the x angle. Altering the y axis makes things rotate about their longitudinal axis (y rotation is also known as roll, x = pitch, z = yaw: pitch, roll, yaw) so an offset straight infront of the centre object will not move the moving object at all.

Some bits of code for fairground rides. I did want to release these myself with the aid of a modeller, but it never happened. It could have been a very interesting Myriad lot (quite a big one too).

Ferris wheel.

This ferris wheel has 8 cars which all stay upright as the wheel turns, adding more is easy as the code is designed to be expanded. Note: this code assumes $fwcar([0-9]+), $fwwheel and $fwcenter are already set up as a correctly loaded models. $fwcar([0-9]+) is the ferris wheel car model, $fwwheel is the ferris wheel and $fwcenter is an invisible model at the centre of the wheel used to place all the cars. You can if you want easilly replace the globals with floats, save space, it may even be recommended, I just cba again, I use them occasionally.

CODE
:labelferris100
0005: $fwxangle = 45.0 // Initial angle of the ferris wheel
0005: $fwyangle = 0.0 // Initial TILT of the wheel, alter it if you REALLY want
0005: $fwzangle = 90.0 // Initial direction of the ferris wheel
0005: $fwradius = 30.0 // Radius of ferris wheel, set to yours
0004: $fwwait = 10 // Delay in ms
0005: $fwspeed = 5.0 // Angle to increment by each step
0005: $fwcars = 8 // Change to add more cars, they will be placed automatically but you will need to add them to the list, I couldn't be bothered to use my own arrays (they're so hard to implement even I can't be arsed!)
0002: jump ££labelferris110

// List of cars part one (add your extras to both)
:labelferris101
0084: $fwcar = $fwcar0
0051: return
0084: $fwcar = $fwcar1
0051: return
0084: $fwcar = $fwcar2
0051: return
0084: $fwcar = $fwcar3
0051: return
0084: $fwcar = $fwcar4
0051: return
0084: $fwcar = $fwcar5
0051: return
0084: $fwcar = $fwcar6
0051: return
0084: $fwcar = $fwcar7
0051: return

// Part 2
:labelferris102
0084: $fwcar0 = $fwcar
0051: return
0084: $fwcar1 = $fwcar
0051: return
0084: $fwcar2 = $fwcar
0051: return
0084: $fwcar3 = $fwcar
0051: return
0084: $fwcar4 = $fwcar
0051: return
0084: $fwcar5 = $fwcar
0051: return
0084: $fwcar6 = $fwcar
0051: return
0084: $fwcar7 = $fwcar
0051: return

// You don't need to change owt below here.

:labelferris110
0093: 0@ = int_to_float $fwcars
0005: $fwcarang = 360.0
0077: $fwcarang /= 0@

:labelferris120
0001: wait $fwwait
0084: $fwloop = $fwcars
0010: $fwloop *= 10
0453: set_object $fwwheel angle $fwxangle $fwyangle $fwzangle
0453: set_object $fwcenter angle $fwxangle $fwyangle $fwzangle
0089: 4@ = $fwzangle

:labelferris125
0004: $fwget = ££labelferris101
0004: $fwset = ££labelferris102
0008: $fwget += $fwloop
0008: $fwset += $fwloop
0050: gosub $fwget
0400: 0@ 1@ 2@ get_point_on_object_plane $fwcenter $fwradius 0.0 0.0
// Not sure about the parameter order, I'm using the DB here and it's different to MB which I'm coding in if you hadn't noticed.
01BC: put_object $fwcar at 0@ 1@ 2@
0051: gosub $fwset
005D: 4@ += $fwcarang
0453: set_object $fwcenter angle $fwxangle $fwyangle 4@
000C: $fwloop -= 10
00D6: if 0
0030:   $fwloop > 0
004D: jump_if_false ££labelferris120
0002: jump ££labelferris125


Thats all you're getting for now, if I can be arsed I may give you more code for more bits. That code should work but it's done from memory so don't blame me if it doesn't. It doens't reference the player so doesn't have a definition check, if you want to add one, go for it. It is also designed for extensibility over speed so if you know exactly how many cars you will always want to do you can modify it to be much better for only that number (remove all the lookup tables etc). Also with a little modification this can be modded to run ALL your ferris wheels (should you want lots) to save on code space.

justa_newbie
  • justa_newbie

    Square Civilian

  • Members
  • Joined: 31 Jul 2005

#3

Posted 08 December 2005 - 07:14 PM

Y_Less....just because nobody's answered, doesn't mean
nobody's interested. wink.gif

I've got no application for what you're doing right now,
but I still think it's cool sh*te and I'm glad you are
exploring it. biggrin.gif

Cheers.

justa_newbie

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#4

Posted 08 December 2005 - 07:32 PM

That is true, but still no-one replied and it was dying so I had to bump it. I was also 'exploring' this technique over a year ago, I just never posted it, so these are just results, not active experiments.

PlatinumSerb
  • PlatinumSerb

    ...

  • Members
  • Joined: 23 Mar 2004

#5

Posted 09 December 2005 - 05:40 AM

This seems really interesting. I'll have a go at a ferris wheel(model) tomorrow, and if I cant get the code to work I'll send it to you.



random_download
  • random_download

    :o

  • Members
  • Joined: 07 Mar 2004

#6

Posted 09 December 2005 - 05:47 PM

Nice, this would be a great addition to Myriad tounge.gif

Few things: first, I think that at the end of your code where you have "0030: $fwloop > 0" I think it should be opcode 0028 ($int > int, not $float > float). Also, is the $fwset gosub needed? As far as I can tell it just sets a var from the array to the car handle it already is. Next, wouldn't this move the cars around in a circle place-by-place, as in they will jump 360/$fwcars degrees each time? Where as it would be better if they moved 1 degree at a time, then a wait sets the time between each degree like:

CODE
:ferriscalculations //gosub
0093: 6@ = int_to_float $fwloop
0017: 6@ /= 10
0089: 4@ = $fwcarang
006B: 4@ *= 6@
005B: 4@ += 5@
00D6: if 0
8031:    NOT 4@ >= 360.0
004D: jump_if_false ££labelferrisleave
000F: 4@ -= 360.0

:labelferrisleave
0051: return //end gosub

//code starts here
:labelferris110
0093: 0@ = int_to_float $fwcars
0005: $fwcarang = 360.0
0077: $fwcarang /= 0@

:labelferriscomplete
0089: 5@ = $fwzangle

:labelferris120
0001: wait $fwwait
0084: $fwloop = $fwcars
0010: $fwloop *= 10
0453: set_object $fwwheel angle $fwxangle $fwyangle $fwzangle
0453: set_object $fwcenter angle $fwxangle $fwyangle $fwzangle

:labelferris125
0004: $fwget = ��labelferris101
0008: $fwget += $fwloop
0050: gosub $fwget
0050: gosub ££ferriscalculations
0453: set_object $fwcenter angle $fwxangle $fwyangle 4@
0400: 0@ 1@ 2@ get_point_on_object_plane $fwcenter $fwradius 0.0 0.0
// Not sure about the parameter order, I'm using the DB here and it's different to MB which I'm coding in if you hadn't noticed.
01BC: put_object $fwcar at 0@ 1@ 2@
000C: $fwloop -= 10
00D6: if 0
8028:   NOT $fwloop > 0
004D: jump_if_false ££labelferris125
0009: 5@ += 1.0 //When finished looping through each car move to the next degree and jump to where there is a wait
00D6: if 0
0037:   5@ >= $fwzangle //if it got too big reset to original starting position (as it has come full circle)
004D: jump_if_false ££labelferriscomplete
0002: jump ££labelferris120

This can probably be optimised somewhere.

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#7

Posted 09 December 2005 - 08:25 PM

I think you misunderstood the code (or I wrote it wrong, that was whipped up in minutes when I made the post so could easily be wrong). What it's MEANT to do it, each time the thread loops (i.e. every time it reaches the first wait). The MAIN WHEEL turns however many small degrees you set it to. Then the hidden centre object turns that little bit and 360/$fwcars $fwcar times (i.e. it does a full circle in bits and ends up pointing in the same direction as the main wheel (though due to rounding errors and other limitations this position is then set to EXACTLY the wheels rotation so the cars don't slowly get out of synch)). Every time the hidden centre reaches a point round it's full circle, it calculates an offset from there and places the next car in the array there. No, $fwget isn't needed, I was just modifying code for PatricW's Marina Car Park Mod from memory as it was similar.

But yes, the overall effect is that the wheel turns little bits (it was one of the user definable variables at the top IIRC) while the centre spins round in larger bits to calculate the new positions of the cars round the edge, spaced at your 360/$fwcars.

random_download
  • random_download

    :o

  • Members
  • Joined: 07 Mar 2004

#8

Posted 11 December 2005 - 12:58 PM

Ah, I see what you mean. I think you just missed out using the $fwspeed var , you need an "$fwzangle += $fwspeed" somewhere in labelferris120? Then mabye a check to see if the angle is > 360.

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#9

Posted 11 December 2005 - 04:37 PM Edited by Y_Less, 01 May 2008 - 02:17 PM.

Ah I didn't did I, I'm glad one of us is awake. Cheers.

CODE
:labelferris100
0005: $fwxangle = 45.0 // Initial angle of the ferris wheel
0005: $fwyangle = 0.0 // Initial TILT of the wheel, alter it if you REALLY want
0005: $fwzangle = 90.0 // Initial direction of the ferris wheel
0005: $fwradius = 30.0 // Radius of ferris wheel, set to yours
0004: $fwwait = 10 // Delay in ms
0005: $fwspeed = 5.0 // Angle to increment by each step
0005: $fwcars = 8 // Change to add more cars, they will be placed automatically but you will need to add them to the list, I couldn't be bothered to use my own arrays (they're so hard to implement even I can't be arsed!)
0002: jump ££labelferris110

// List of cars part one (add your extras to both)
:labelferris101
0084: $fwcar = $fwcar0
0051: return
0084: $fwcar = $fwcar1
0051: return
0084: $fwcar = $fwcar2
0051: return
0084: $fwcar = $fwcar3
0051: return
0084: $fwcar = $fwcar4
0051: return
0084: $fwcar = $fwcar5
0051: return
0084: $fwcar = $fwcar6
0051: return
0084: $fwcar = $fwcar7
0051: return

// Part 2
:labelferris102
0084: $fwcar0 = $fwcar
0051: return
0084: $fwcar1 = $fwcar
0051: return
0084: $fwcar2 = $fwcar
0051: return
0084: $fwcar3 = $fwcar
0051: return
0084: $fwcar4 = $fwcar
0051: return
0084: $fwcar5 = $fwcar
0051: return
0084: $fwcar6 = $fwcar
0051: return
0084: $fwcar7 = $fwcar
0051: return

// You don't need to change owt below here.

:labelferris110
0093: 0@ = int_to_float $fwcars
0005: $fwcarang = 360.0
0077: $fwcarang /= 0@

:labelferris120
0001: wait $fwwait
0084: $fwloop = $fwcars
0010: $fwloop *= 10
0453: set_object $fwwheel angle $fwxangle $fwyangle $fwzangle
0453: set_object $fwcenter angle $fwxangle $fwyangle $fwzangle
0089: 4@ = $fwzangle

:labelferris125
0004: $fwget = ££labelferris101
0004: $fwset = ££labelferris102
0008: $fwget += $fwloop
0008: $fwset += $fwloop
0050: gosub $fwget
0400: 0@ 1@ 2@ get_point_on_object_plane $fwcenter $fwradius 0.0 0.0
// Not sure about the parameter order, I'm using the DB here and it's different to MB which I'm coding in if you hadn't noticed.
01BC: put_object $fwcar at 0@ 1@ 2@
0051: gosub $fwset
005D: 4@ += $fwcarang
0453: set_object $fwcenter angle $fwxangle $fwyangle 4@
000C: $fwloop -= 10
00D6: if 0
0018:   $fwloop > 0
004D: jump_if_false ££labelferris130
0002: jump ££labelferris125

:labelferris130
0059: $fwzangle += $fwspeed
00D6: if 0
0030:   $fwzangle > 360.0
004D: jump_if_false ££labelferris120
000D: $fwzangle -= 360.0
0002: jump ££labelferris120


Right, no wonder you couldn't understand it, my bad, sorry. This is the updated code, I added the angle update and fixed one opcode where for some reason I was using gtegf instead of gtgi, which is a bit of a random mix up.

chickenplucker
  • chickenplucker

    Old school

  • Members
  • Joined: 17 Jul 2002

#10

Posted 07 January 2006 - 05:55 PM Edited by chickenplucker, 07 January 2006 - 05:59 PM.

I always wanted a ferris wheel, so I thought I'd try your cool looking code out Y_less. But since I'm just a dumb map modder I need some help.
When I try to compile it in BW's mission builder at

000D: $fwzangle -=360.0
(second from bottom)

it says paramiter 2 not set.
I honestly did try to search around to see if I could solve this on my own before bumping.

Heres a pic of my Wheel (very crappy jpg)
Just to make sure, the cars are placed with the script right?
If you would some models of diffrent rides to experiment with just pm me and I'll see what I can do.

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#11

Posted 07 January 2006 - 06:15 PM

I think your problem is that I may have missed a space between the '=' and the number so the builder doesn't find the number.

And I would LOVE some models, if you need help with doing the code PM me.

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#12

Posted 23 June 2006 - 09:26 AM

Huge bump but meh. I was working on a little project the other day and I found a bug in the set_object_rotation OpCode (yes, the OpCode, not my code). X and Z rotatation are calculated around the world X and Z axies, Y rotation is done around the models Y axis (don't know how I missed this before).

An example of the problems this can cause is if you set an object to an initial rotation of:

90.0 0.0 0.0

the object will be facing the ground and rotating the model around either the Y or Z axies will look exactly the same.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users