Instructables Universe in Three.js (9 / 13 stap)

Stap 9: Three.js: Hit-prestaties met 20.000 punten in 3D

ThreeJS heeft ons een lange manieren gekregen. In plaats van 20.000 punten van platte, onbewogen, we nu 20.000 punten in drie-ruimte, ongelijke centra ronddraaien en met de uiteindelijke belofte dat we de camera, ook, en echt animeren kunt onderzoeken binnen de Melkweg.

Maar wanneer u een ster onttrekt, hoe snel kunnen ThreeJS vinden? Vrij snel blijkt. Vanaf dit het schrijven ondersteunt geen ThreeJS raycaster kruispunten voor ParticleSystems (womp womp), maar gelukkig iemand anders postuur zulks uiterlijk. Er zijn tal van vorken u kunt gebruiken, of gewoon de code zelf ingevoegd in de bibliotheek en bouwen van een aangepaste kopie. Dit is wat u zou toevoegen aan Raycaster.js (aangepast uit gelijkaardige code vond ik helemaal, graag hier):

 canvasClickEvent: function(e){ e.preventDefault(); e.stopPropagation(); this.resetInteractionTimer(); // stops "auto mode" from resuming for 90s var vector = new THREE.Vector3( ( e.clientX / Galaxy.Settings.width ) * 2 - 1, - ( e.clientY / Galaxy.Settings.height ) * 2 + 1, 0.5 ); var projector = new THREE.Projector(); projector.unprojectVector( vector, this.camera ); var ray = new THREE.Raycaster( this.camera.position, vector.sub( this.camera.position ).normalize() ); // If there are already selected stars out in the field, ie, from an author constellation or related group, // we assume the user is trying to select one of those. However, if each of these systems contains // only a single vertex, that indicates the user may just be clicking around individually. So don't use pre-selected // stars for the intersection in that case. var intersectSystems = this.particleSystemsArray, that = this; if (!_.isUndefined(this.__glowingParticleSystems)) { _.each(this.__glowingParticleSystems,function(system){ if (system.geometry.vertices.length !== 1) { // intersect with the glowing systems instead intersectSystems = that.__glowingParticleSystems; } }); } // When the camera is very close to the star that's selected, distance is deceiving. We basically need to adjust hit tolerance based on the distance to camera // Calculate the distance camera --> star by converting star's position to world coords, then measuring // intersection.point = Vector3 // intersection.object = ParticleSystem it's a part of var getCameraDistanceForHit = function(intersection){ var intersectionVect = intersection.point.clone(); intersectionVect = intersection.object.localToWorld(intersectionVect); return intersectionVect.distanceTo(that.camera.position.clone()); }; // intersects sorted by distance so the first item is the "best fit" var intersects = _.sortBy(ray.intersectObjects( intersectSystems, true ),function(intersection){ return getCameraDistanceForHit(intersection) / intersection.distance; }); // When a hit is too close to the camera for its hit tolerance, it doesn't count. Remove those values. intersects = _.filter(intersects, function(intersection){ return getCameraDistanceForHit(intersection) / intersection.distance > 100; }); if ( intersects.length > 0 ) { this.selectVertex(intersects[0]) } else { // no intersections are within tolerance. this.reset({projectTagsAddAfterCameraReset: true}); } }, 

Zodra de bibliotheek is gebouwd op de juiste manier (ik laat dit als een oefening voor de lezer), krijgen van het snijpunt van een gebruikershandleiding kraan of een muisklik is vrij eenvoudig: het is een raycaster met behulp van de huidige camerapositie, de scène, en de (x, y) coördinaten van de klik van de gebruiker. Psuedo-code:

 TweenMax.to(upCurrent,duration/1.5,{x: upGoal.x,y: upGoal.y,z: upGoal.z}); TweenMax.to(targetCurrent,duration/1.5,{x: center.x,y: center.y, z: center.z}); TweenMax.to(positionCurrent,duration,{x: home.x,y: home.y, z: home.z,ease: Power1.easeInOut, onUpdate: function(){ // every frame, update the camera with all of the current values IN THIS ORDER! that.target = new THREE.Vector3(targetCurrent.x,targetCurrent.y,targetCurrent.z); that.camera.position.set(positionCurrent.x,positionCurrent.y,positionCurrent.z); that.camera.up.set( upCurrent.x,upCurrent.y,upCurrent.z ); that.camera.lookAt(that.target.clone()); that.camera.updateProjectionMatrix(); }, onComplete: function(){ // when the animation finishes that.endAnimation(); that.firstClick = true; if (typeof callback === "function") callback(); }, onStart: that.startAnimation }) 

De realiteit van de code voor dit project met zijn meerdere particlesystems en de wens te vinden van de dichtstbijzijnde snijpunt tussen snijpunten van alle van de particlesystems is enigszins complexer. Plus, zo goed uitgelegd door Jens Arps, Er is wat mysterie vlees bij het draaien van een screen-punt in een 3D-vector (je ziet dit ook in mijn code: nieuwe drie. Vector3 ((e.clientX / Galaxy.Settings.width) * 2-1,-(e.clientY / Galaxy.Settings.height) * 2 + 1, 0,5)):

 Galaxy.Settings = Galaxy.Settings || {}; Galaxy.CameraMotions = function(camera){ _.bindAll(this,'zoomToFitPointsFrom','startAnimation','endAnimation','cameraSetupForParameter','beginAutomaticTravel'); this.target = Galaxy.Settings.cameraDefaultTarget.clone(); this.camera = camera; // delete this property eventually this.firstClick = true; this.isAnimating = false; } Galaxy.CameraMotions.prototype = { constructor: Galaxy.CameraMotions, startAnimation: function(){ // startAnimation refers to user-initiated animations. The default animation must be removed if ongoing. this.endAutomaticTravel(); this.isAnimating = true; }, endAnimation: function(){this.isAnimating = false;}, zoomAndDollyToPoint: function(point,callback){ if (this.isAnimating === true) return; // temporarily: the first click will zoom in, and we'll strafe after that. if (this.firstClick === false) { //this.strafeFromPointToPoint(this.target,point,callback); this.zoomToFitPointsFrom([point],this.CAMERA_RELATION.TOWARD_CENTER,callback); return; } this.firstClick = false; var that = this, pointClone = point.clone(), cameraPath = this.cameraPathToPoint(this.camera.position.clone(), point.clone()), currentPosition = {now: 0}, duration = 1.3, upClone = Galaxy.Settings.cameraDefaultUp.clone(), targetCurrent = this.target.clone(); TweenMax.to(targetCurrent,duration/1.5,{ x:pointClone.x, y:pointClone.y, z:pointClone.z }); TweenMax.to(currentPosition,duration,{ now:0.8, onUpdate: function(){ var pos = cameraPath.getPoint(currentPosition.now); that.target = new THREE.Vector3(targetCurrent.x,targetCurrent.y,targetCurrent.z); that.camera.position.set(pos.x,pos.y,pos.z); that.camera.up.set(upClone.x,upClone.y,upClone.z); that.camera.lookAt(that.target); that.camera.updateProjectionMatrix(); }, onStart: that.startAnimation, onComplete: function(){ that.endAnimation(); if (typeof callback === "function") callback(); } }); }, cameraPathToPoint: function(fromPoint,toPoint){ var spline = new THREE.SplineCurve3([ fromPoint, new THREE.Vector3( (toPoint.x-fromPoint.x)*0.5 + fromPoint.x, (toPoint.y-fromPoint.y)*0.5 + fromPoint.y, (toPoint.z-fromPoint.z)*0.7 + fromPoint.z), toPoint ]); return spline; }, strafeFromPointToPoint: function(fromPoint,toPoint,callback){ var dest = toPoint.clone(), current = this.camera.position.clone(), duration = 0.5, that = this; dest.sub(fromPoint.clone()); dest.add(current.clone()); //console.log("\n\n",fromPoint,toPoint,current,dest); if (that.isAnimating === true) return; TweenMax.to(this.camera.position,duration,{x: dest.x,y: dest.y, z: dest.z, onComplete: function(){ that.endAnimation(); that.camera.lookAt(toPoint.clone()); that.target = toPoint.clone(); if (typeof callback === "function") callback(); }, onStart: that.startAnimation }) }, reset: function(callback){ var duration = 2, that = this, home = Galaxy.Settings.cameraDefaultPosition.clone(), center = Galaxy.Settings.cameraDefaultTarget.clone(), upGoal = Galaxy.Settings.cameraDefaultUp.clone(), upCurrent = this.camera.up.clone(), targetCurrent = this.target.clone(), positionCurrent = this.camera.position.clone(); // never do anything when nothing will suffice. The callback should have no delay. if (this.camera.up.equals(Galaxy.Settings.cameraDefaultUp) && this.camera.position.equals(Galaxy.Settings.cameraDefaultPosition) && this.target.equals(Galaxy.Settings.cameraDefaultTarget)) { duration = 0.1; } if (that.isAnimating === true) return; TweenMax.to(upCurrent,duration/1.5,{x: upGoal.x,y: upGoal.y,z: upGoal.z}); TweenMax.to(targetCurrent,duration/1.5,{x: center.x,y: center.y, z: center.z}); TweenMax.to(positionCurrent,duration,{x: home.x,y: home.y, z: home.z,ease: Power1.easeInOut, onUpdate: function(){ that.target = new THREE.Vector3(targetCurrent.x,targetCurrent.y,targetCurrent.z); that.camera.position.set(positionCurrent.x,positionCurrent.y,positionCurrent.z); that.camera.up.set( upCurrent.x,upCurrent.y,upCurrent.z ); that.camera.lookAt(that.target.clone()); that.camera.updateProjectionMatrix(); }, onComplete: function(){ that.endAnimation(); that.firstClick = true; if (typeof callback === "function") callback(); }, onStart: that.startAnimation }) }, CAMERA_RELATION : { ABOVE: 0, SAME_ANGLE: 1, TOWARD_CENTER: 2 }, zoomToFitPointsFrom: function(pointList,cameraRelation,callback) { if (!_.has(_.values(this.CAMERA_RELATION),cameraRelation)) { // console.log(_.values(this.CAMERA_RELATION)); console.error(cameraRelation + " is not one of RELATIVE_LOCATION"); return; } if (this.isAnimating === true) return; // pointList assumed to already be in world coordinates. Figure out bounding sphere, then move camera relative to its center var bSphere = new THREE.Sphere(new THREE.Vector3(0,0,0),5); bSphere.setFromPoints(pointList); // how far away do we need to be to fit this sphere? var targetDistance = (bSphere.radius / (Math.tan(Math.PI*this.camera.fov/360))), cameraPositionEnd, that = this, duration = 1, up = this.camera.up.clone(), currentCameraPosition = this.camera.position.clone(); switch (cameraRelation) { case 0: // CAMERA_RELATION.ABOVE cameraPositionEnd = bSphere.center.clone().add(new THREE.Vector3(40,40,targetDistance)); break; case 1: // CAMERA_RELATION.SAME_ANGLE dollies the camera in/out such that these points become visible var center = bSphere.center.clone(), currentPos = that.camera.position.clone(), finalViewAngle = currentPos.sub(center).setLength(targetDistance); cameraPositionEnd = bSphere.center.clone().add(finalViewAngle); // to prevent camera from going under the background plane: cameraPositionEnd.z = Math.max(cameraPositionEnd.z,40); break; case 2: // CAMERA_RELATION.TOWARD_CENTER Draws a line from world origin through the bounding sphere's center point, // and puts the camera at the end of a vector twice that length. cameraPositionEnd = bSphere.center.clone().multiplyScalar(2); if (cameraPositionEnd.length() < 125) cameraPositionEnd.setLength(125); // It's weird when the camera gets too close to stars in the middle break; } var cameraTargetCurrent = {x: this.target.x, y: this.target.y, z: this.target.z}; var cameraTargetEnd = bSphere.center.clone(); // that.logVec('up',that.camera.up.clone()); // that.logVec('target',that.target.clone()); // that.logVec('position',that.camera.position.clone()); TweenMax.to(cameraTargetCurrent,duration/1.5,{x: cameraTargetEnd.x,y: cameraTargetEnd.y, z: cameraTargetEnd.z}); // DO NOT change "up" for high angle. It gets screwy and spins the camera unpleasantly. if (cameraRelation !== 0) {TweenMax.to(up,duration/1.5,{x: 0,y: 0, z: 1});} TweenMax.to(currentCameraPosition,duration,{x: cameraPositionEnd.x,y: cameraPositionEnd.y, z: cameraPositionEnd.z, onUpdate: function(){ that.target = new THREE.Vector3(cameraTargetCurrent.x,cameraTargetCurrent.y,cameraTargetCurrent.z); that.camera.position.set(currentCameraPosition.x,currentCameraPosition.y,currentCameraPosition.z); that.camera.up.set( up.x,up.y,up.z ); that.camera.lookAt(that.target.clone()); that.camera.updateProjectionMatrix(); }, onComplete: function(){ // that.logVec('up',that.camera.up.clone()); // that.logVec('target',that.target.clone()); // that.logVec('position',that.camera.position.clone()); that.endAnimation(); if (typeof callback === "function") callback(); }, onStart: that.startAnimation }) }, showThreePointsNicely: function(pointList, callback){ // Find a camera location and rotation such that the first point appears towards the bottom of the screen, and // the other two appear up and to the left and right. Or so. if (this.isAnimating === true) return; this.firstClick = false; if (!_.isArray(pointList)) { throw new Error ("Array of points required for showThreePointsNicely"); } else if (pointList.length !== 3) { // just show the first one. this.zoomAndDollyToPoint(pointList[0],callback); return; } var pointZero = pointList[0].clone(); // look at the world from the perspective of the star that will be centered: var viewFromPointZero = function(vector){ return vector.clone().sub(pointZero.clone()); }; // The "bisect" vector is a central angle between the Left and Right stars that we're trying to make visible on screen, along with vector Zero var bisectLocal = viewFromPointZero( pointList[1]).add(viewFromPointZero( pointList[2])).multiplyScalar(0.5); // The linear path would be described as.... var A = viewFromPointZero(pointList[1]); var B = viewFromPointZero(pointList[2]); var theta = Math.acos(A.clone().dot(B.clone()) / A.length() / B.length() ); var distanceAwayBasedOnAngle = Math.min(Math.max(theta*2.5,2),4); var cameraEndPosition = pointZero.clone().sub(bisectLocal.clone().multiplyScalar(distanceAwayBasedOnAngle)); var cameraStartPosition = this.camera.position.clone(); var cameraPathMidpoint = cameraEndPosition.clone().add(cameraStartPosition.clone()).multiplyScalar(0.5); // The circular path around the linear path's midpoint would be, then: var radius = cameraStartPosition.clone().sub(cameraPathMidpoint.clone()).length(); var that = this; var worldPointOnCircularPath = function(t){ var x = radius * Math.cos(t); var y = radius * Math.sin(t); var vectorPointLocal = new THREE.Vector3(x,y,0); return vectorPointLocal.add(cameraPathMidpoint.clone()); }; // backsolve the start angle for the circular path. It's the inverse of x=a+r*cos(theta) => theta = acos((x-a)/r); var startPointRelativeToMidpoint = cameraStartPosition.clone().sub(cameraPathMidpoint.clone()); var startAngle = Math.atan(startPointRelativeToMidpoint.y/startPointRelativeToMidpoint.x); // Is this the start angle or the end angle? It's one or the other, but we need to know which.... The other will be this + PI if (worldPointOnCircularPath(startAngle).setZ(0).distanceTo(cameraStartPosition.clone().setZ(0)) > 100) { // gotta start halfway around instead. such is the world of inverse trig functions startAngle += Math.PI; } var parameters = { t: startAngle, z: cameraStartPosition.clone().z }, duration = 2.0, up = that.camera.up.clone(); var pointZeroClone = pointZero.clone(); TweenMax.to(that.target,duration/1.5,{x: pointZeroClone.x,y: pointZeroClone.y,z: pointZeroClone.z}); TweenMax.to(up,duration/1.5,{x: 0,y: 0, z: 1}); TweenMax.to(parameters,duration,{ t: startAngle - Math.PI, z: cameraEndPosition.clone().z, ease: Power1.easeOut, onUpdate: function(){ var xyCurrent = worldPointOnCircularPath(parameters.t); that.camera.position.set(xyCurrent.x,xyCurrent.y,parameters.z); that.camera.up.set( up.x,up.y,up.z ); that.camera.lookAt(that.target); that.camera.updateProjectionMatrix(); }, onComplete: function(){ that.endAnimation(); if (typeof callback === "function") callback(); }, onStart: that.startAnimation }); }, // The camera can also "travel" while in unattended mode. This behavior requires some code to parametrically define and then animate the complex path, // But it is somewhat different in kind from the user-initiated camera motions described above. beginAutomaticTravel: function(){ // This function absolutely positively must begin from the camera home positions. // console.log('commencing automatic camera travel'); var obj = {cameraParameter: Math.PI/2}, that=this, loopConstants = this.loopConstants(); this.reset(function(){ that.__automaticCameraAnimation = TweenMax.to(obj, loopConstants.duration, { cameraParameter: 5*Math.PI/2, onUpdate:function(){ that.cameraSetupForParameter(obj.cameraParameter,loopConstants); }, ease: null, repeat: -1 // loop infinitely }); }); }, loopConstants: function(){ var galaxyLoopStart = new THREE.Vector3(200,0,15), targetLoopStart = new THREE.Vector3(200,200,5), upLoopStart = new THREE.Vector3(0,0,1); return { duration : 400, // seconds galaxyLoopStart : galaxyLoopStart, targetLoopStart: targetLoopStart, upLoopStart: upLoopStart, galaxyLoopToHome : Galaxy.Settings.cameraDefaultPosition.clone().sub(galaxyLoopStart.clone()), targetLoopToHome : Galaxy.Settings.cameraDefaultTarget.clone().sub(targetLoopStart.clone()), upLoopToHome : Galaxy.Settings.cameraDefaultUp.clone().sub(upLoopStart.clone()) } }, cameraSetupForParameter: function(cameraParameter,loopConstants){ var pos,lookAt = loopConstants.targetLoopStart.clone(),up = loopConstants.upLoopStart.clone(); if (cameraParameter < 2*Math.PI && cameraParameter > Math.PI) { cameraParameter -= Math.PI; // go a full circle around the galaxy pos = new THREE.Vector3(200*Math.cos(cameraParameter),200*Math.sin(cameraParameter),15); var copy = pos.clone(); lookAt = new THREE.Vector3(copy.x ,copy.y + copy.x,5); } else { // after going a full circle around the galaxy, animate all camera characteristics to the "home" position, then repeat from start var pathMultiplier = Math.sin(cameraParameter ); // good from 0 to PI. Outside that range, this goes negative and looks haywire. pos = loopConstants.galaxyLoopStart.clone().add(loopConstants.galaxyLoopToHome.clone().multiplyScalar(pathMultiplier)); lookAt = loopConstants.targetLoopStart.clone().add(loopConstants.targetLoopToHome.clone().multiplyScalar(pathMultiplier)); up = loopConstants.upLoopStart.clone().add(loopConstants.upLoopToHome.clone().multiplyScalar(pathMultiplier)); } this.camera.position.set(pos.x,pos.y,pos.z); this.camera.up.set(up.x,up.y,up.z); this.target = lookAt; this.camera.lookAt(lookAt); this.camera.updateProjectionMatrix(); }, endAutomaticTravel: function(){ if (this.__automaticCameraAnimation) { this.__automaticCameraAnimation.kill(); } }, // DEBUGGING TOOLS logVec: function(message,vec){ console.log(message + ": " + vec.x + " " + vec.y + " " + vec.z); }, addTestCubeAtPosition: function(position){ var cube = new THREE.Mesh( new THREE.CubeGeometry( 5, 5, 5 ), new THREE.MeshNormalMaterial() ); cube.position = position.clone(); Galaxy.Scene.add( cube ); } } 

En het blijkt te zijn vrij pittig!

Gerelateerde Artikelen

The Instructables University Game

The Instructables University Game

Ik had niet gepland op het invoeren van de "How to play wedstrijd" want ik niet echt een gameconsole ben. Na het nadenken, kwam ik met The Instructables Universiteit Game. Ik heb geprobeerd om mijn volwassen zoon aan bij de pret hier, maar zijn
Verleden projecten/Pre Instructables...

Verleden projecten/Pre Instructables...

I wish I would have found Instructables two or three years ago. Ik kon een deurklink van een veel meer hebben bijgedragen. Met mijn recente verplaatsen onvermijdelijk dat heb ik besloten om enkele foto's van eerdere projecten in mijn huidige huis ver
Jus te gaan met een gebraden

Jus te gaan met een gebraden

hoewel dit dom eenvoudig is, ik ben voortdurend verbaasd over het aantal mensen die geïntimideerd, zijn wanneer het gaat om het maken van een simpele jus te gaan met een gebraden. Deze jus werkt ruim aardappelen, besprenkeld over het vlees of de volg
Gedetailleerde geweven Duct Tape portefeuilles Instructable

Gedetailleerde geweven Duct Tape portefeuilles Instructable

Ja, ja, het is een ander Duct Tape wallet instructable.Hoe saai, juiste?De reden dat ik dit doe is dat ik proberen zal te doen samenballen van kennis over het bouwen van allerlei soorten Duct Tape portefeuilles en ingaan op veel aspecten zodat u zal
Steven Universe jurk

Steven Universe jurk

Een goede vriend van mij houdt Steven Universe, dus ik haar deze jurk als een gift van de verjaardag maakte. Ik denk dat dit is een echt mooie jurk, en zou een geweldig cosplay of Halloween kostuum!Ik maakte haar ook een volledige set van kat vinger
TestrBot: De $300 Universal testmachine

TestrBot: De $300 Universal testmachine

UPDATE 9-2-15: ik vrijgegeven een batch van testresultaten die aantonen dat mijn beweegredenen voor terwijl "infill"-ontwerp is de beste!* Wat is TestrBot?TestrBot is een $300 Universal Test Machine (UTM) en kan worden gebruikt voor het uitvoere
Steven Universe lumi inkodye ondergoed met crystal gem Garnet

Steven Universe lumi inkodye ondergoed met crystal gem Garnet

Een van de dingen die mijn geld kan niet kopen is prima super held/favoriet karakter ondergoed (of elke merch echt) voor dames. Elke vorm van boksers schijnt beschikbaar te zijn, en soms heb ik geprobeerd kopen sommige "jongens" grootte ondergoe
SUMO&nbsp;:&nbsp;&nbsp;Slimme&nbsp;/*&nbsp;*&nbsp;Smart&nbsp;Pulse&nbsp;Monitor&nbsp;*&nbsp;Author&nbsp;:&nbsp;Geeve&nbsp;George&nbsp;*&nbsp;Instructables&nbsp;:&nbsp;*/&nbsp;#include&nbsp;const&nbsp;int&nbsp;analo

SUMO&nbsp;:&nbsp;<youtube&nbsp;id="lDKM7UKUL5A"></youtube>&nbsp;Slimme&nbsp;/*&nbsp;*&nbsp;Smart&nbsp;Pulse&nbsp;Monitor&nbsp;*&nbsp;Author&nbsp;:&nbsp;Geeve&nbsp;George&nbsp;*&nbsp;Instructables&nbsp;:&nbsp;*/&nbsp;#include&nbsp;const&nbsp;int&nbsp;analo

src = "HalloIedereen,Ik benGeeveGeorgeeen15jaaroudeMaker/elektronicaHobbyist.IliefdeComputerVisie,AndroïdeOntwikkelingenAlgoritmeDesign.Iamop dit momentin11eRangComputerWetenschapStudentbijWeinigRockIndischeSchool.:)Zoekenmeerovermebij:href = "h
DIY zelf geactiveerd PRIVATE UNIVERSE

DIY zelf geactiveerd PRIVATE UNIVERSE

dit is mijn allereerste ooit Instructables uploaden dus, wees voorzichtig met mij.Ik maakte dit voor een kleine galerie ruimte in een ARI genoemd Constance in Hobart, Tasmanië, Australië, en is speciaal ontworpen om te worden geactiveerd wanneer mens
Knex verstek zagen instructies

Knex verstek zagen instructies

het is teruggekeerd! Ja, na 3 jaar, heb ik eindelijk besloten om te posten van instructies van mijn verstek zaag. Deze zaag is net als de oude is, behalve een paar kleine kleurwijzigingen te geven een meer consistent kleurenschema. Voor degenen onder
Pimp mijn PSP hoofdstuk 1 uw one-stop Instructable voor al uw PSP behoeften!

Pimp mijn PSP hoofdstuk 1 uw one-stop Instructable voor al uw PSP behoeften!

Dit instructable leert u sommige unieke dingen die uw PSP in een Multi-Media beest transformeren zal.Dit instructable zal u tonen hoe te:1. update uw PSP (officiële Firmware, niet Custom Firmware)2. video's toevoegen aan uw PSP (hoofdstuk 2)3. foto's
Met de Switch()-instructie als Sequencing Control

Met de Switch()-instructie als Sequencing Control

In dit Instructable, zal wij gaan over de "switch()"-instructie en het gebruik in de programmering. De instructie switch is een krachtig hulpmiddel voor het organiseren van uw programma, gemakkelijk kunt u complexe stroomdiagrammen doorlopen.In
Overleven in het wild-het meest unieke instructable tot nu toe

Overleven in het wild-het meest unieke instructable tot nu toe

u hebben net wakker om jezelf te vinden op de grond in het wild.  Vóór het opstaan vanuit je liggende positie realiseert je je dat, naast het feit dat niet in uw eigen warme comfortabele bed, u hebben gewekt in het kreupelhout onder het bladerdak van
Stalen Python Knex achtbaan - instructies

Stalen Python Knex achtbaan - instructies

is terug iedereen-staal Python!Dit model is de recreatie van mijn oudere ontwerp, met een paar kleine wijzigingen, aangezien ik nooit had specifieke foto's van het origineel. Dit ontwerp heeft natuurlijk zijn gebreken, zodat u wellicht om te knoeien