Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
3D Rocket Launch to the Moon
#1
Maybe I have over-sold this program in this thread title.  This program simulates a rocket-launch from Cape Canaveral to the Moon.  But there are (as you will undoubtedly expect) very great simplifications.
The program uses _MAPTRIANGLE(3D) - I'm a real fan of this - to make a 3D world in which a rocket travels.  And the rocket itself is a 3D object.
The motion of the rocket is determined by (approximations to) proper rocket mathematics.  Pre-launch the rocket is filled with propellant which has two thirds of the total mass.  At ignition, propellant pellets are ejected with high velocity to provide an upward thrust for the rocket.  As the overall weight of the rocket decreases with time until the fuel is used up the acceleration of the rocket increases.
The rocket starts at Cape Canaveral and stands vertically.  When the rocket is launched it travels upwards and directly forwards to eventually land at The Sea of Tranquillity on the Moon.  The rocket has a constant force of gravity downwards - there is no travel in space with a reduction of gravity.  So after the fuel is used up the rocket behaves as a ballistic object and describes a parabolic path.
The Cape Canaveral and Moon landscapes and the rocket and its fuel pellets are all 3D objects in the _MAPTRIANGLE(3D) space.
When the fuel pellets are being ejected, the display may look as if this is just a graphical effect.  But as I said, there is real rocket physics going on at all stages of the flight.
There is some audio accompanying the display, and you may recognise an appropriate musical track.  I recommend that you use ear-buds if possible to get the benefit of Richard Strauss's composition.
The first time that the program is run, the music track is played alone.  Subsequent runs have the rocket launch sequence with Saturn-5 launch sounds - this drowns out the Strauss.

Unzip the file and place the folder in the QB64 folder:

.zip   Rocket MapTriangle.zip (Size: 4.04 MB / Downloads: 42)

The fun part of this program was getting the rocket mathematics working to a reasonable degree of faithfulness, bearing in mind the simplifications.  The rocket starts vertically and needs some guidance to tilt it off the vertical to begin the travel forward.  My first attempts started with the rocket already tilted forward and I quickly discovered that the rocket then immediately ploughs itself into the ground.  Doubtless Werner von Braun discovered how to easily blow up the rocket on the launch pad when he was directing his V2 missiles at London.
In this program, at ignition individual propellant pellets are fired sequentially backwards.  Just after ignition, the rocket is still too heavy for the thrust to move the rocket upward, but after a short period that thrust is sufficient to give lift-off and upward acceleration.  When the speed of the rocket is sufficient there is a short period where the rocket is (manually) tilted forward slightly.  Then the guided tilting is stopped and the rocket moves forward by thrust and gravity.  The rocket is accelerated upwards and forwards.  When the fuel is used up the rocket moves under gravity alone, continuing upwards with decreasing velocity and forwards with constant velocity.  Eventually the rocket begins to fall back down and lands on the Moon.  There is no soft landing which is more HG Wells rather than Apollo.  BREAKING NEWS:  Apparently some YouTube expert says that we never made it to the Moon.  This program is an illusion.
The attached graphs show the progression of altitude, range (distance from launch site forwards out of the screen) and pitch (angle of the rocket from horizontal).

There were a number of compromises to be made in the program.  In order to give a good display over the entire flight a large program window was required.  A full 1080 HD window size would have been desirable but I restricted this so that most users can view the whole window.  At maximum height the rocket is partly off-screen.  The displayed rocket size is clearly way too large for the given flight, but even so the rocket and fuel pellets are rather small at Cape Canaveral.
If the window size is still too large to fit in your display I have made a window-capture video which you may wish to view - but the fun part is to look at the coding.  NB The audio quality in the video is lower than if running the program.

I should apologise for the descent into whimsicality at the end of the program.  It was an Irresistible Temptation.

   




   

Code: (Select All)
'Rocket Launch, Travel & (Crash-)Land program by Magdha 30/10/25 QB64 v2.0

'Five stages of flight:
'1. Initial Vertical Thrust (craft too heavy) - Ignition
'2. Vertical Lift-off and acceleartion
'3. Guided Tilt
'4. Unguided Thrust
'5. Free flight under gravity (parabolic)

CONST False = 0, True = NOT False
CONST Sparks% = 5000, PreLaunch% = 1250, Ignition% = 200, FRatio! = 0.5, VSparks! = 1, deltaT! = 0.1
CONST ZOffset% = 1000, NoArcs%% = 64, Rad%% = 40, HalfLength%% = 150, NoseHeight%% = 50
CONST PelletSize%% = 5, LauchHeight% = 50, ArtificialDelay% = 40
CONST TranquilityBase% = -250, YDisp! = 0.85, ZDisp! = 7.2, LaunchPadZ% = -1500

DIM Pellets&(8), Fuel%%(Sparks%, 1), FuelStats!(Sparks%, 3) 'Each fuel pellet has (x,y,z), angle of thrust; propelled speed is constant
DIM MapFromCylinder%(NoArcs%%), MapToClinder!(NoArcs%%, 1), MapFromLogo%(8), MapToLogo!(8, 1)
DIM MapFromNoseCone%(NoArcs%%, 1), MapToNoseCone!(NoArcs%%, 3)
DIM SHARED Gamma!, Phi!, Z!, Y!, X!

IF _FILEEXISTS("Zarathustra.txt") THEN
    DoBlast%% = True
ELSE
    OPEN "Zarathustra.txt" FOR OUTPUT AS #1
    PRINT #1, True
    CLOSE #1
END IF

RANDOMIZE (TIMER)
_TITLE "Thus Spake Zarathustra"

Apollo11& = _LOADIMAGE("Armstrong-Collins-Aldrin.jpg", 33) 'Map this to rocket body
Canaveral& = _LOADIMAGE("Canaveral.jpg", 33)
Tranquility& = _LOADIMAGE("Tranquility A.jpg", 33)
ItsARocket& = _LOADIMAGE("Sputnik.jpg", 33)
Zarathustra& = _SNDOPEN("Also Sprach Zarathustra A.mp3")
Landed& = _SNDOPEN("The Eagle Has Landed.mp3")
GiantLeap& = _SNDOPEN("Giant Leap.mp3")
Blast& = _SNDOPEN("Blast.mp3")

'Rocket Body Image Map
ApolloI% = _WIDTH(Apollo11&) - 1
ApolloJ% = _HEIGHT(Apollo11&) - 1
FOR K%% = 0 TO NoArcs%%
    MapFromCylinder%(K%%) = CINT(K%% * ApolloI% / NoArcs%%)
    MapToClinder!(K%%, 0) = Rad%% * COS(2 * _PI * K%% / NoArcs%%) 'z
    MapToClinder!(K%%, 1) = Rad%% * SIN(2 * _PI * K%% / NoArcs%%) 'x
NEXT K%%
SputnikWidth% = _WIDTH(ItsARocket&)
FOR K%% = -4 TO 4
    MapFromLogo%(K%% + 4) = CINT((K%% + 4) * SputnikWidth% / 8)
    MapToLogo!(K%% + 4, 0) = (Rad%% + 1) * COS(2 * _PI * K%% / NoArcs%%) 'z The +1 is needed otherwise logo not displayed
    MapToLogo!(K%% + 4, 1) = (Rad%% + 1) * SIN(2 * _PI * K%% / NoArcs%%) 'x
NEXT K%%

'Nosecone Image
TempImage& = _NEWIMAGE(201, 201, 32)
_DEST TempImage&
COLOR _RGB32(255, 253, 208), _RGBA32(90, 0, 90, 0)
CLS
FOR I% = 0 TO 200
    I1%% = I% - 100
    FOR J% = 0 TO 200
        J1%% = J% - 100
        R! = SQR(I1%% * I1%% + J1%% * J1%%)
        Th! = _ATAN2(J1%%, I1%%)
        IF R! <= 101 THEN PSET (I%, J%), _RGB32(255 - 100 * (1 - 0.5 * SIN(Th!)) - 0.25 * R!, 253 - 100 * (1 - 0.5 * SIN(Th!)) - 0.25 * R!, 208 - 100 * (1 - 0.5 * SIN(Th!)) - 0.25 * R!)
    NEXT J%
NEXT I%
FOR K%% = 0 TO NoArcs%%
    MapFromNoseCone%(K%%, 0) = CINT(100 * COS(2 * _PI * K%% / NoArcs%%)) + 100 'x
    MapFromNoseCone%(K%%, 1) = CINT(100 * SIN(2 * _PI * K%% / NoArcs%%)) + 100 'y
    MapToNoseCone!(K%%, 0) = Rad%% * COS(2 * _PI * K%% / NoArcs%%) 'z
    MapToNoseCone!(K%%, 1) = Rad%% * SIN(2 * _PI * K%% / NoArcs%%) 'x
    MapToNoseCone!(K%%, 2) = (Rad%% - 1) * COS(2 * _PI * K%% / NoArcs%%) 'z
    MapToNoseCone!(K%%, 3) = (Rad%% - 1) * SIN(2 * _PI * K%% / NoArcs%%) 'x
NEXT K%%
NoseCone& = HardwareImage&(TempImage&, True) 'Map this to rocket nose cone & base

'Fuel Pellet
FOR K%% = 0 TO 8
    TempImage& = _NEWIMAGE(2 * PelletSize%% + 1, 2 * PelletSize%% + 1, 32)
    _DEST TempImage&
    COLOR _RGB32(255, 255, 225 - 20 * K%%), _RGBA32(90, 0, 90, 0)
    CLS
    CIRCLE (PelletSize%%, PelletSize%%), PelletSize%%
    PAINT (PelletSize%%, PelletSize%%)
    Pellets&(K%%) = HardwareImage&(TempImage&, True)
NEXT K%%

'Fuel stats: Pellet colour, pre-launch/launched/burnt out
FOR P% = 1 TO Sparks%
    Fuel%%(P%, 0) = P% MOD 9 'Pellet colour factor
    Fuel%%(P%, 1) = False 'Pre-launch state (stationary inside rocket)
    Alpha! = RND * 2 * _PI
    FuelStats!(P%, 0) = (Rad%% - PelletSize%%) * SIN(Alpha!) 'x
    FuelStats!(P%, 2) = (Rad%% - PelletSize%%) * COS(Alpha!) 'z
    FuelStats!(P%, 1) = -HalfLength%% + PelletSize%% 'y
NEXT P%

'Banner
TempImage& = _NEWIMAGE(940, 70, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (0, 0), "Rocket Launch Demonstration"
Banner0& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(300, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (80, 0), "Cape"
_PRINTSTRING (0, 65), "Canaveral"
Banner1& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(360, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (100, 0), "Mare"
_PRINTSTRING (0, 65), "Tranquillitatis"
Banner2& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(390, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (90, 0), "Rocket"
_PRINTSTRING (0, 65), "On Launchpad"
Banner3& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(200, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (0, 0), "Ignition"
Banner4& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(200, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (0, 0), "Lift-Off"
Banner5& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(380, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (80, 0), "Guided"
_PRINTSTRING (0, 65), "Pitch Forward"
Banner6& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(380, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (30, 0), "Propulsion"
_PRINTSTRING (90, 65), "Only"
Banner7& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(400, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (20, 0), "Fuel Used Up"
_PRINTSTRING (20, 65), "- Free Flight"
Banner8& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(380, 130, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 60, "bold")
_PRINTSTRING (40, 0), "At Maximum"
_PRINTSTRING (100, 65), "Altitude"
Banner9& = HardwareImage&(TempImage&, True)
TempImage& = _NEWIMAGE(860, 100, 32)
_DEST TempImage&
COLOR _RGB32(255, 255, 255), _RGBA32(90, 0, 90, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\arial.ttf", 46, "bold")
_PRINTSTRING (0, 0), "That's One Small App From Magdha..."
Banner10& = HardwareImage&(TempImage&, True)

'Initial Conditions and dummy variables
Dum1%% = 0
Dum2%% = 0
Dum3%% = 0
Z! = 0
Y! = HalfLength%% + LauchHeight%
X! = 0
Vz! = 0
Vy! = 0
VFactor! = 2.5
N% = 0
Theta! = _PI / 2
g! = VSparks! * SIN(Theta!) / ((Sparks% - Ignition%) + (Sparks% * FRatio!))
Zara%% = False
Gamma! = -_PI / 5
Saturn%% = False
Fps%% = 120

'Screen
SCREEN _NEWIMAGE(1000, 850, 32)
_SCREENMOVE 50, 0
_DEST 0
_DISPLAYORDER _HARDWARE , _SOFTWARE

LOCATE 1, 1
PRINT "Altitude:"
LOCATE 2, 1
PRINT "Range:"
LOCATE 3, 1
PRINT "Pitch:"

Count& = 0
Paused%% = False
DoExit%% = False
WHILE NOT DoExit%%
    _LIMIT Fps%%

    K$ = INKEY$
    IF K$ <> "" THEN
        IF UCASE$(K$) = "P" THEN
            Paused%% = NOT Paused%%
        ELSEIF ASC(K$) = 27 THEN
            DoExit%% = True
        END IF
        K$ = ""
    END IF

    IF NOT Paused%% THEN
        Count& = Count& + 1
        CALL ReadOut((Y!), 1)
        CALL ReadOut((Z!), 2)
        CALL ReadOut((Theta!), 3)

        IF Count& > PreLaunch% THEN 'Start fuel ignition after set delay (while displaying information banners)
            IF N% <= Sparks% THEN
                'Using fuel
                IF N% >= 1 THEN
                    Fuel%%(N%, 1) = True
                    FuelStats!(N%, 3) = Theta!
                    'Rotate by Theta/Phi about the x- axis
                    y1! = FuelStats!(N%, 1)
                    FuelStats!(N%, 2) = FuelStats!(N%, 2) * COS(Phi!) + y1! * SIN(Phi!) 'z
                    FuelStats!(N%, 1) = 0 - FuelStats!(N%, 2) * SIN(Phi!) + y1! * COS(Phi!) 'y
                    FuelStats!(N%, 2) = FuelStats!(N%, 2) + ZDisp! * Z! + LaunchPadZ% 'z
                    FuelStats!(N%, 1) = FuelStats!(N%, 1) + YDisp! * Y! + TranquilityBase% 'y
                END IF
                N% = N% + 1
                'Thrust from fuel pellet ejection
                VImp! = VSparks! / ((Sparks% - N%) + (Sparks% * FRatio!))
                IF VImp! * SIN(Theta!) > g! THEN
                    'Rocket accelerates when thrust overcomes gravity
                    deltaVz! = VImp! * COS(Theta!)
                    deltaVy! = VImp! * SIN(Theta!) - g!
                    deltaZ! = Vz! + deltaVz! * deltaT! / 2
                    deltaY! = Vy! + deltaVy! * deltaT! / 2
                    Z! = Z! + deltaZ!
                    IF Z! < 0 THEN Z! = 0
                    Y! = Y! + deltaY!
                    Vz! = Vz! + deltaVz!
                    Vy! = Vy! + deltaVy!
                    'Rotate rocket body
                    Gamma! = Gamma! - 0.00265
                    'When half of fuel has been used allow a short period of guided pitch change
                    IF N% > Sparks% / 2 THEN
                        IF N% < (Sparks% / 2) + 500 THEN
                            'Guided tilting region
                            Theta! = Theta! - 0.00008 'This figure "derived" from trial & error
                        ELSE
                            'Angle determined by propulsion
                            Theta! = ATN(Vy! / Vz!)
                        END IF
                    END IF
                END IF
            ELSEIF Y! > 0 THEN
                'Fuel used up - Flight is free parabolic curve
                Gamma! = Gamma! - 0.003
                deltaVz! = 0
                deltaVy! = -g!
                deltaZ! = Vz! + deltaVz! * deltaT! / 2
                deltaY! = Vy! + deltaVy! * deltaT! / 2
                Z! = Z! + deltaZ!
                Y! = Y! + deltaY!
                Vz! = Vz! + deltaVz!
                Vy! = Vy! + deltaVy!
                Theta! = ATN(Vy! / Vz!)
            END IF
        END IF

        'Display the rocket
        Phi! = _PI / 2 - Theta! 'The angle used to determine mapping
        IF Saturn%% THEN
            'Map Rocket
            FOR K%% = 1 TO NoArcs%%
                'Rocket Body
                'Movement & Rotations
                CALL Manoeuvre((MapToClinder!(K%% - 1, 0)), (MapToClinder!(K%%, 0)), (MapToClinder!(K%%, 0)), (MapToClinder!(K%% - 1, 0)), (MapToClinder!(K%% - 1, 1)), (MapToClinder!(K%%, 1)), (MapToClinder!(K%%, 1)), (MapToClinder!(K%% - 1, 1)), (HalfLength%%), (HalfLength%%), (-HalfLength%%), (-HalfLength%%), (True), x13!, x23!, x33!, x43!, y13!, y23!, y33!, y43!, z13!, z23!, z33!, z43!)
                'Map to Display
                _MAPTRIANGLE (MapFromCylinder%(NoArcs%% - K%% + 1), ApolloJ%)-(MapFromCylinder%(NoArcs%% - K%%), ApolloJ%)-(MapFromCylinder%(NoArcs%% - K%%), 0), Apollo11& TO(x13!, y13!, z13! - ZOffset%)-(x23!, y23!, z23! - ZOffset%)-(x33!, y33!, z33! - ZOffset%)
                _MAPTRIANGLE (MapFromCylinder%(NoArcs%% - K%%), 0)-(MapFromCylinder%(NoArcs%% - K%% + 1), 0)-(MapFromCylinder%(NoArcs%% - K%% + 1), ApolloJ%), Apollo11& TO(x33!, y33!, z33! - ZOffset%)-(x43!, y43!, z43! - ZOffset%)-(x13!, y13!, z13! - ZOffset%)
                'END IF
                'Rocket Nocecone
                'Movement & Rotations
                CALL Manoeuvre(0, (MapToNoseCone!(K%%, 0)), (MapToNoseCone!(K%% - 1, 0)), Dum1%%, 0, (MapToNoseCone!(K%%, 1)), (MapToNoseCone!(K%% - 1, 1)), Dum2%%, (HalfLength%% + NoseHeight%), (HalfLength%%), (HalfLength%%), Dum3%%, (True), x14!, x24!, x34!, x44!, y14!, y24!, y34!, y44!, z14!, z24!, z34!, z44!)
                'Map to Display
                _MAPTRIANGLE (100, 100)-(MapFromNoseCone%(K%%, 0), MapFromNoseCone%(K%%, 1))-(MapFromNoseCone%(K%% - 1, 0), MapFromNoseCone%(K%% - 1, 1)), NoseCone& TO(x14!, y14!, z14! - ZOffset%)-(x24!, y24!, z24! - ZOffset%)-(x34!, y34!, z34! - ZOffset%)
                'Rocket Base
                'Movement & Rotations
                CALL Manoeuvre(0, (MapToNoseCone!(K%%, 2)), (MapToNoseCone!(K%% - 1, 2)), Dum1%%, 0, (MapToNoseCone!(K%%, 3)), (MapToNoseCone!(K%% - 1, 3)), Dum2%%, (1 - HalfLength%%), (1 - HalfLength%%), (1 - HalfLength%%), Dum3%%, (False), x15!, x25!, x35!, x45!, y15!, y25!, y35!, y45!, z15!, z25!, z35!, z45!)
                'Map to Display
                _MAPTRIANGLE (100, 100)-(MapFromNoseCone%(K%%, 0), MapFromNoseCone%(K%%, 1))-(MapFromNoseCone%(K%% - 1, 0), MapFromNoseCone%(K%% - 1, 1)), NoseCone& TO(x15!, y15!, z15! - ZOffset%)-(x25!, y25!, z25! - ZOffset%)-(x35!, y35!, z35! - ZOffset%)
            NEXT K%%
            'Rocket Logo
            FOR K%% = 1 TO 8
                'Movement & Rotations
                CALL Manoeuvre((MapToLogo!(K%% - 1, 0)), (MapToLogo!(K%%, 0)), (MapToLogo!(K%%, 0)), (MapToLogo!(K%% - 1, 0)), (MapToLogo!(K%% - 1, 1)), (MapToLogo!(K%%, 1)), (MapToLogo!(K%%, 1)), (MapToLogo!(K%% - 1, 1)), (HalfLength%%), (HalfLength%%), (-HalfLength%%), (-HalfLength%%), (True), x16!, x26!, x36!, x46!, y16!, y26!, y36!, y46!, z16!, z26!, z36!, z46!)
                'Map to Display
                _MAPTRIANGLE (MapFromLogo%(K%% - 1), 0)-(MapFromLogo%(K%%), 0)-(MapFromLogo%(K%%), ApolloJ%), ItsARocket& TO(x16!, y16!, z16! - ZOffset%)-(x26!, y26!, z26! - ZOffset%)-(x36!, y36!, z36! - ZOffset%)
                _MAPTRIANGLE (MapFromLogo%(K%%), ApolloJ%)-(MapFromLogo%(K%% - 1), ApolloJ%)-(MapFromLogo%(K%% - 1), 0), ItsARocket& TO(x36!, y36!, z36! - ZOffset%)-(x46!, y46!, z46! - ZOffset%)-(x16!, y16!, z16! - ZOffset%)
            NEXT K%%

            'Propellant Pellets - display and move
            FOR P% = 1 TO Sparks%
                IF Fuel%%(P%, 1) THEN
                    'Map Pellet if it is active
                    _MAPTRIANGLE (0, 0)-(PelletSize%%, 0)-(PelletSize%%, PelletSize%%), Pellets&(Fuel%%(P%, 0)) TO(FuelStats!(P%, 0) - PelletSize%%, FuelStats!(P%, 1) + PelletSize%%, FuelStats!(P%, 2) - ZOffset%)-(FuelStats!(P%, 0) + PelletSize%%, FuelStats!(P%, 1) + PelletSize%%, FuelStats!(P%, 2) - ZOffset%)-(FuelStats!(P%, 0) + PelletSize%%, FuelStats!(P%, 1) - PelletSize%%, FuelStats!(P%, 2) - ZOffset%)
                    _MAPTRIANGLE (PelletSize%%, PelletSize%%)-(0, PelletSize%%)-(0, 0), Pellets&(Fuel%%(P%, 0)) TO(FuelStats!(P%, 0) + PelletSize%%, FuelStats!(P%, 1) - PelletSize%%, FuelStats!(P%, 2) - ZOffset%)-(FuelStats!(P%, 0) - PelletSize%%, FuelStats!(P%, 1) - PelletSize%%, FuelStats!(P%, 2) - ZOffset%)-(FuelStats!(P%, 0) - PelletSize%%, FuelStats!(P%, 1) + PelletSize%%, FuelStats!(P%, 2) - ZOffset%)
                    'Propel pellet backwards in the direction opposite to that of the rocket at that time
                    FuelStats!(P%, 1) = FuelStats!(P%, 1) - VSparks! * VFactor! * SIN(FuelStats!(P%, 3)) 'y
                    FuelStats!(P%, 2) = FuelStats!(P%, 2) - VSparks! * VFactor! * COS(FuelStats!(P%, 3)) 'z
                    IF FuelStats!(P%, 1) < TranquilityBase% - 10 THEN Fuel%%(P%, 1) = False
                END IF
            NEXT P%

        END IF
    END IF

    'Map Landscapes
    _MAPTRIANGLE (0, 0)-(1167, 0)-(1167, 850), Canaveral& TO(-500, TranquilityBase%, -3000 - ZOffset%)-(500, TranquilityBase%, -3000 - ZOffset%)-(500, TranquilityBase%, -50 - ZOffset%)
    _MAPTRIANGLE (1167, 850)-(0, 850)-(0, 0), Canaveral& TO(500, TranquilityBase%, -50 - ZOffset%)-(-500, TranquilityBase%, -50 - ZOffset%)-(-500, TranquilityBase%, -3000 - ZOffset%)
    _MAPTRIANGLE (0, 0)-(626, 0)-(626, 758), Tranquility& TO(-500, TranquilityBase%, 100 - ZOffset%)-(500, TranquilityBase%, 100 - ZOffset%)-(500, TranquilityBase%, 800 - ZOffset%)
    _MAPTRIANGLE (626, 758)-(0, 758)-(0, 0), Tranquility& TO(500, TranquilityBase%, 800 - ZOffset%)-(-500, TranquilityBase%, 800 - ZOffset%)-(-500, TranquilityBase%, 100 - ZOffset%)

    'Sounds
    SELECT CASE Count&
        CASE PreLaunch%
            IF DoBlast%% THEN _SNDPLAY Blast&
        CASE 2950
            _SNDPLAY Zarathustra&
        CASE 13850
            _SNDPLAY Landed&
        CASE 14250
            _SNDPLAY GiantLeap&
    END SELECT

    'Banners
    SELECT CASE Count&
        CASE IS <= 350
            _PUTIMAGE (100, 120), Banner0&
        CASE 400 TO 600
            IF Count& = 400 THEN _FREEIMAGE Banner0&
            _PUTIMAGE (680, 400), Banner1&
        CASE 650 TO 850
            IF Count& = 650 THEN _FREEIMAGE Banner1&
            _PUTIMAGE (400, 700), Banner2&
        CASE 900 TO 1100
            IF Count& = 900 THEN
                _FREEIMAGE Banner2&
                Saturn%% = True
            END IF
            _PUTIMAGE (550, 400), Banner3&
        CASE PreLaunch% TO PreLaunch% + Ignition%
            IF Count& = PreLaunch% THEN
                _FREEIMAGE Banner3&
                Fps%% = 60 'Temporarily slow down display to more readily observe the ignition stage
                VFactor! = 5
            END IF
            _PUTIMAGE (400, 120), Banner4&
        CASE PreLaunch% + Ignition% + ArtificialDelay% TO PreLaunch% + Ignition% + ArtificialDelay% + 450
            IF Count& = PreLaunch% + Ignition% + ArtificialDelay% THEN
                _FREEIMAGE Banner4&
                Fps%% = 120
                VFactor! = 2.5
            END IF
            _PUTIMAGE (400, 110), Banner5&
        CASE 3751 TO 4230
            IF Count& = 3751 THEN _FREEIMAGE Banner5&
            _PUTIMAGE (340, 100), Banner6&
        CASE 4250 TO 4500
            IF Count& = 4250 THEN _FREEIMAGE Banner6&
            _PUTIMAGE (340, 90), Banner7&
        CASE 6251 TO 6500
            IF Count& = 6251 THEN _FREEIMAGE Banner7&
            _PUTIMAGE (340, 60), Banner8&
        CASE 9270 TO 9500
            IF Count& = 9270 THEN _FREEIMAGE Banner8&
            _PUTIMAGE (340, 300), Banner9&
        CASE 14250 TO 14550
            IF Count& = 13200 THEN _FREEIMAGE Banner9&
            _PUTIMAGE (70, 150), Banner10&

    END SELECT

    _DISPLAY

WEND

SYSTEM

FUNCTION HardwareImage& (ImageName&, Scrap%%)
    HardwareImage& = _COPYIMAGE(ImageName&, 33)
    IF Scrap%% THEN _FREEIMAGE ImageName&
END FUNCTION

SUB ReadOut (E!, C%%)
    IF C%% = 3 THEN
        E1! = E! * 180 / _PI
    ELSE
        E1! = E!
        IF E1! < 0 THEN E1! = 0
    END IF
    Q% = CINT(E1!)
    S$ = STR$(Q%)
    LOCATE C%%, 11
    PRINT "      "
    LOCATE C%%, 16 - LEN(S$)
    PRINT S$
END SUB

SUB Manoeuvre (z10!, z20!, z30!, z40!, x10!, x20!, x30!, x40!, y10!, y20!, y30!, y40!, MagicRoundabout%%, x19!, x29!, x39!, x49!, y19!, y29!, y39!, y49!, z19!, z29!, z39!, z49!)
    IF MagicRoundabout%% THEN
        'Rotate about y-axis
        z1! = z10! * COS(Gamma!) + x10! * SIN(Gamma!)
        x1! = -z10! * SIN(Gamma!) + x10! * COS(Gamma!)
        z2! = z20! * COS(Gamma!) + x20! * SIN(Gamma!)
        x2! = -z20! * SIN(Gamma!) + x20! * COS(Gamma!)
        z3! = z30! * COS(Gamma!) + x30! * SIN(Gamma!)
        x3! = -z30! * SIN(Gamma!) + x30! * COS(Gamma!)
        z4! = z40! * COS(Gamma!) + x40! * SIN(Gamma!)
        x4! = -z40! * SIN(Gamma!) + x40! * COS(Gamma!)
        y1! = y10!
        y2! = y20!
        y3! = y30!
        y4! = y40!
    ELSE
        z1! = z10!
        x1! = x10!
        z2! = z20!
        x2! = x20!
        z3! = z30!
        x3! = x30!
        z4! = z40!
        x4! = x40!
        y1! = y10!
        y2! = y20!
        y3! = y30!
        y4! = y40!
    END IF
    'Then rotate by Phi about the x- axis (pitch)
    z12! = z1! * COS(Phi!) + y1! * SIN(Phi!)
    y12! = -z1! * SIN(Phi!) + y1! * COS(Phi!)
    z22! = z2! * COS(Phi!) + y2! * SIN(Phi!)
    y22! = -z2! * SIN(Phi!) + y2! * COS(Phi!)
    z32! = z3! * COS(Phi!) + y3! * SIN(Phi!)
    y32! = -z3! * SIN(Phi!) + y3! * COS(Phi!)
    z42! = z4! * COS(Phi!) + y4! * SIN(Phi!)
    y42! = -z4! * SIN(Phi!) + y4! * COS(Phi!)
    x12! = x1!
    x22! = x2!
    x32! = x3!
    x42! = x4!
    'Then add X!, Y! & Z!
    x19! = x12! + X!
    x29! = x22! + X!
    x39! = x32! + X!
    x49! = x42! + X!
    y19! = y12! + YDisp! * Y! + TranquilityBase%
    y29! = y22! + YDisp! * Y! + TranquilityBase%
    y39! = y32! + YDisp! * Y! + TranquilityBase%
    y49! = y42! + YDisp! * Y! + TranquilityBase%
    z19! = z12! + ZDisp! * Z! + LaunchPadZ%
    z29! = z22! + ZDisp! * Z! + LaunchPadZ%
    z39! = z32! + ZDisp! * Z! + LaunchPadZ%
    z49! = z42! + ZDisp! * Z! + LaunchPadZ%
END SUB

When I discovered _MAPTRIANGLE(3D) I found it interesting.  The fun is working out the appropriate mapping to go from a 2D image to a 3D image.  Skilled QB64 programmers will use OpenGL but that has remained beyond me, and at present I seem to be in a _MAPTRIANGLE(3D) - Conic Sections coding phase.  My two previous programs (https://qb64phoenix.com/forum/showthread.php?tid=4025, https://qb64phoenix.com/forum/showthread.php?tid=4052) had objects moving in hyperbolic paths and then in a 3D circular path.  In this program I have an object moving along a parabolic path, and I'm investigating elliptical motion.
Reply


Messages In This Thread
3D Rocket Launch to the Moon - by Magdha - 11-03-2025, 01:05 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Moon Phases Magdha 0 227 11-25-2025, 11:34 AM
Last Post: Magdha
  3D Sun-Earth-Moon Simulation Magdha 5 679 11-14-2025, 07:07 PM
Last Post: bplus

Forum Jump:


Users browsing this thread: 1 Guest(s)