jogl, polygon as own object/class - draw

I want to draw a polygon as an own object in its own class, not as part of the display method. I havn't found that much about it, hope someone here can help me.
public PolygonalGameObject(GameObject parent, double points[],
double[] fillColour, double[] lineColour) {
super(parent);
myPoints = points;
myFillColour = fillColour;
myLineColour = lineColour;
}
public void drawSelf(GL2 gl) {
// TODO: Write this method
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glBegin(GL2.GL_POLYGON);{
for (int i = 0; i < myPoints.length; i += 2) {
double x = myPoints[i];
double y = myPoints[i + 1];
gl.glVertex2d(x, y);
}
}gl.glEnd();
}
A GameObject contains several polygonalGameObjects in a scene graph/tree
I'm pretty new at this (both programming and graphics), so if anybody got some good tutorials please post then!
Many Thanks!

You need a current OpenGL context to draw something with OpenGL and that's why you need to call your drawing methods in GLEventListener.display(GLAutoDrawable), the OpenGL context is guaranteed to be current on this thread during a call of this method. It's possible to use JOGL without GLEventListener but it's more dangerous especially if you're a beginner and it's a waste of time because it doesn't give any flexibility whereas it forces you to handle the life cycle of your drawable by yourself. Using a GLEventListener doesn't prevent you from creating your own classes, you just have to call your drawing methods directly or indirectly in display().
If you have any questions about JOGL, rather ask them on the official forum. You can look at the wiki too. You need to learn plain OpenGL to use JOGL, you can read the OpenGL Red Book. If you're very new at programming, I don't think you should start with graphics, you should start with something a lot more simple first in order to learn the basic principles of Java programming before learning 2D and the principles of 3D computer graphics.

Related

Actionscript 3: Drawing lines and bitmaps the right way

I'm just getting started with Flash/ActionScript and it seems to be the general consensus to create Sprites, Bitmaps, MovieClips, etc for various objects in order to represent pictures and other graphics.
However, the way I'm used to writing games and whatnot in other languages is to just loop repeatedly and each frame use something similar to the Graphics object to redraw the scene on the main Sprite. Is this how it's also done in Flash, and is it good practice? I can do it this way, but I'm wondering if there's some Flash ecosystem standard instead.
Here's an example of the way I'm used to:
public class MyApp extends Sprite
{
public function MyApp()
{
var t:Timer = new Timer(20);
t.addEventListener(TimerEvent.TIMER, update);
t.start();
}
public function update(e:TimerEvent)
{
this.graphics.clear();
//Rendering code and updating of objects.
}
}
Is this acceptable?
Well, it depends.
In Flash, you have the option of relying on the Flash Player's vector rasterizer and rendering system, which will figure out all the redrawing for you. For instance, you can draw once to a Sprite then simply apply transforms to the sprite (set x, y, width, height, rotation, scaleX, scaleY, transform.matrix, transform.colorTransform, etc). Any of these objects could be a vector shape or a bitmap, and you can also use cacheAsBitmap and cacheAsBitmapMatrix for even more redraw optimization. The Flash Player will only redraw areas that change, on the frame that they change. I would consider this the traditional "Flash way".
Using the Graphics API is just a programmatic way to create vector shape data. Think of it as a code alternative to drawing in the Flash IDE. You could draw using Graphics once when the object is created, or if you needed to change the actual shape (ie not just the transform) you are correct that you would clear() and redraw it. However, ideally you would not be doing that a lot. If you find yourself redrawing the shape a lot, you might want to move to a pre-rendered sprite-sheet approach. In that case you use BitmapData to more quickly copy pre-drawn pixel data to a Bitmap object. This is generally faster than relying on the vector rasterizer to render your Graphics commands, as long as you use the fast pixel methods like copyPixels(). This is probably closer to the sort of rendering systems you are used to in other platforms that don't have a vector rasterizer built in.
Lastly, it's worth noting that the newest (and fastest) way to render objects in Flash is completely different than all that. It's called Stage3D and it uses a completely different rendering pipeline than the vector rasterizer. It's powered by GPU rendering APIs, so it's blazing fast (great for games) but has no vector rasterizing abilities. It can be used for both 3D and 2D. It's a bit more involved to work with, but there are some useful frameworks to make it easier, most notably the Starling 2D framework.
Hope that helps.
The "Flash way" is to use EnterFrame event instead of using timer to draw. You must make your calculation whenever you want but let flash draw you scene.
It works the same way in actionscript.
public class App extends Sprite // adding "my" to identifier names doesn't add any information, so there's no real point in doing it
{
public function App()
{
addEventListener(Event.ENTER_FRAME, update); // "each frame"
}
private function update(e:Event):void //not just parameters of functions have a type, but also their return value
{
graphics.clear(); // no need for "this" here
//Rendering code and updating of objects.
}
}
Keep in mind that the Graphics API is vector based and as such will only draw so many things before dropping performance.
Sprite is a general purpose container, not to be confused with what the term "sprite" stands for in a sprite sheet.
What you are probably referring to when saying "main Sprite" is some rectangular region of pixels that you can manipulate.In this case, a BitmapData is what you want, which is displayed with a Bitmap object.
BitmapData does not offer a graphics property. Essentially, drawing vectors and manipulating pixels are treated separately in As3. If you want to draw a line in a BitmapData object, you'd have to first draw the line as a vector into a Sprite (or better Shape, if all you want to do is draw on it) using its graphics property, then use draw() of BitmapData to set its pixels according to the drawn line.

How do I execute functions in actionscript 3?

I'm completely new to actionscript (as3, not as2) and am having some problems with some simple functions and variables. Everything is in one .fla using the actions panel.
How do I get functions to execute? Nothing of my shape changes and there is no output.
*I am aware the first change won't be noticeable, I'll add a timer later on.
Here is the code*:
var starBlackWidth = 500;
var starBlackScaleX = 0.5;
function starStretch(){
starBlack.length = starBlackWidth;
trace("Stretched the star.");
}
function starReadjust() {
starBlack.scaleX = starBlackScaleX;
trace("Attempted at readjusting without using the width directly.");
}
As some of the commenters pointed out, yes you need to call the functions you created by adding these two lines of code.
starStretch();
starReadjust();
To expand upon what they said, yes these may be fundamental concepts of programming but if you're new to object oriented programming in as3 and even oop in general this link is extremely helpful at getting you going in as3, its 3 parts and it covers it pretty well!
http://www.untoldentertainment.com/blog/2009/08/25/tutorial-understanding-classes-in-as3-part-1/

AS3: How to supplement function calls in an existing library?

I have a semi-newbie question. I've been programming for years, but all my early experience was pre-OOP and my brain kind of settled that way. I'm also new to Actionscript. So hopefully this is an easy one for somebody.
I'm using as3svgrendererlib to import SVG. It works great, but I need to be able to serialize the graphics it outputs. But I can't serialize sprites, so I have to go all the way down to the IGraphicsData level to get something that I can. But the library doesn't give me that data. It only gives me sprites. So I need to change that.
Since there are only a handful of drawing methods that it ultimately uses (beginFill, drawRect, etc), my thinking is that if I can hook into those and supplement them with my own code to output IGraphicsData as well, then I'll be in business. Now I know I could do that by using "extends" classes, but that would require substantial modification of the library to change all of those standard calls to my custom ones.
So I'm wondering: Is there a magic OOP way to write methods that will universally intercept calls to existing methods without needing to modify the original calls?
Thanks! :)
EDIT: I need resolution-independence, so it's important that I keep the graphics in vector and not convert them to bitmap.
You cannot do this kind of thing in OOP, you either need to override the class (but that might not be possible in your case) or modify the library directly.
However, in your case, a possible solution would be to:
Draw the SVG to a sprite using the library.
Draw the sprite to a BitmapData.
Finally, get the pixel data using getPixels() and serialize it.
Something like this should work;
var sprite:Sprite = new Sprite();
// Add the child to the stage...
// Draw the SVG to the sprite...
var bmpData:BitmapData = new BitmapData(spriteWidth, spriteHeight);
bmpData.draw(sprite);
var pixelData:ByteArray = bmpData.getPixels(new Rectangle(0, 0, bmpData.width, bmpData.height));
// Here serialize the byte array
In this example, note that spriteWidth/spriteHeight are not necessarily "sprite.width" and "sprite.height" (sprites often report dimensions different from what you would expect). So you need to decide in advance the size of the rendered SVG and use this when building the BitmapData.

Split screen in Actionscript 3

I'm trying to make a pure AS3 game, and need a way to split the screen so that two players can have individual "cameras" that follow the around the game world. The problem is that a sprite can't have multiple parents. I'm trying to hack my way around this problem by having classes that duplicate sprites and manage all of their updates, but I'm not getting very far and my code is getting very, very ugly.
Does anyone know a good workaround or method for doing this? I can't seem to find much on-line on the subject.
I think you should use BitmapData copyPixels method
.copyPixels(point_0, rectangle_0)---> FirstPlayerScreen
World.Bitmap -
.copyPixels(point_0, rectangle_0)---> SecondPlayerScreen
Thanks for everyone's suggestions. What I've ended up with is a World class that I can add regular Sprite objects to as children. The World object manages and updates copies of those sprites, and world.getCamera() can be called as many times as necessary to display custom copies of the game world.
The key part is making copies of the sprites, this is the function I wrote to do that:
public function bitmapCopy(original:DisplayObject):Sprite
{
var returnSprite:Sprite = new Sprite();
if (original.width == 0 || original.height == 0) return returnSprite
var x = original.x; var y = original.y
var rotation = original.rotation
original.x = 0; original.y = 0; original.rotation = 0
var bounds:Rectangle = original.getBounds(original.parent)
var m:Matrix = new Matrix()
m.tx = -bounds.x
m.ty = -bounds.y
var bitmapData:BitmapData = new BitmapData( bounds.width, bounds.height, true,
0xFF0000 );
bitmapData.draw(original, m);
var bitmap:Bitmap = new Bitmap( bitmapData );
bitmap.x = bounds.x
bitmap.y = bounds.y
returnSprite.addChild(bitmap);
returnSprite.x = original.x = position.x
returnSprite.y = original.y = position.y
returnSprite.rotation = original.rotation = rotation
return returnSprite;
}
The returned Sprite can be added to the stage and will act in exactly the same way as the original (except for being static, of course). Hopefully this should help anyone else who comes across this problem.
Your theory is on the right track - you're probably just stumbling over your implementation. Organization and keeping things object-oriented will be your best friend in this scenario.
It's hard to give you a good example based off of a limited description of your game, but in general, I'd have a Screen class that can be instantiated multiple times, and I'd keep track of each instantiation (that gives us our multiple "players"). Each Screen has a stage, and you're building your game world on that stage.
The key here is data organization and good communication. Remember, there's only one "world", and you're just showing multiple instances of it. So you'll want a central Model to store data about every object in your singular game world. That Model will drive the rendering of that world to your multiple screens. If a player changes an object on their screen (let's say they move it), then you'll update the Model with that object's new location. Then, you'll broadcast those new coordinates to each Screen instance, so that all of your screens will update.
How you "broadcast" this can vary (and depends largely on the real-time nature of your game). If your game is very real-time and you're running a game loop, then you may just want to pass the objects' data along in every loop, and they'd update that way. If your game isn't as dependent of being real-time, then you can set up event listeners or a custom notification system that'll alert all of the instances of an object to update itself.
I know this is very high-level, but it's hard to give an in-depth answer without more info about your game. Hopefully this helps point you in the right direction - what you're attempting is definitely not simple, so don't get discouraged!
If you develop your game using MVC architecture principles then it should be trivial to draw your game twice, each player having an instance of the game's "view" but positioned according to a different character. If you give a layer mask to each instance then you could put the two instances side by side and so create a split screen effect.
Happy coding!
I'm working on a split screen myself just now:
masking to draw 1 world in 2 branches of your DisplayObject tree (separated cleanly), copying pixels for a split screen is a bad idea
data object to describe the world (not Sprite or DisplayObject)
Works very well so far. I've got 1 level, 2 players who move independently from each other and 2 screens that follow one player at a time. I see the other player in one player's screen and the one player in the other player's screen.
Here is how I did the data object part:
Define a central data object which describes the world and all it's world objects.
Write: make some sprites being able to manipulate 1 object of the world.
Read: update sprites by checking the properties of the world objects. 2 Screens -> 2 sprites for every world object. Check them every frame or try events.

HTML5 Canvas: Calculate the Mouseposition after Zooming and Translating

I try to develope an interactive viewer for vector drawings and want to have the feature of zooming.
The function for zooming works pretty good but now I have the problem to calculate the mouseposition for picking objects.
The event gives back the screen coordinates. The canvas doesn't have a methode to use the transformation matrix in the inverse way.
Does anyone have a solution to this problem?
I made a very small a simple class for keeping track of the transformation matrix.
I added an invert() function for reasons like this. I also made an invertPoint() function but didn't put it in the final version. It's not hard to deduce though, just invert and transform point together.
I often just calculate the appropraite transform with this class and then use setTransform, depending on the application.
I wish I could give you a more specific solution but without a code sample of what you want that'd be hard to do.
Here's the transformation class code. And here's a blog post with a bit of an explanation.
Here are some valuable functions for your library that preserve the matrix state and needed to build up a scene graph:
Transform.prototype.reset = function() {
this.m = [1,0,0,1,0,0];
this.stack = [];
};
Transform.prototype.push = function() {
this.stack.push(this.m.slice());
};
Transform.prototype.pop = function() {
this.m = this.stack.pop();
};