Attach sprite to Bullet - Box2D LibGDX kotlin - android-studio

I'm following some tutorials to be able to implement the parabolic motion. In debug everything works correctly, the parabolic motion responds correctly and the result works. Now I would like to insert a Sprite, and here my problems begin. In fact, the sprite perfectly performs the rotations of the object that is carrying out the parabolic motion but it absolutely does not follow the X and Y coordinates. thank you in advance:
Bullet function:
private fun createBullet() {
val circleShape = CircleShape()
circleShape.radius = 0.5f
circleShape.position = Vector2(convertUnitsToMeters(firingPosition.x), convertUnitsToMeters(firingPosition.y))
val bd = BodyDef()
bd.type = BodyDef.BodyType.DynamicBody
bullet = world!!.createBody(bd)
bullet!!.createFixture(circleShape, 1f)
circleShape.dispose()
val velX = abs(MAX_STRENGTH * -MathUtils.cos(angle) * (distance / 100f))
val velY = abs(MAX_STRENGTH * -MathUtils.sin(angle) * (distance / 100f))
bullet!!.setLinearVelocity(velX, velY)
}
How I'm trying to create sprite:
override fun render(delta: Float) {
sprite.setPosition(bullet!!.position.x - sprite.width / 2,
bullet!!.position.y - sprite.height / 2)
sprite.rotation = Math.toDegrees(bullet!!.angle.toDouble()).toFloat()
batch!!.use {
it.draw(sprite, sprite.x, sprite.y, sprite.originX,
sprite.originY,
sprite.width, sprite.height, sprite.scaleX, sprite.scaleY, sprite.rotation)
}
}

This is an incorrect way to use the Sprite class. There is an unfortunate design decision in libGDX that Sprite is a subclass of TextureRegion, which allows you you pass it to SpriteBatch.draw() as if it is a TextureRegion. When you do this, it ignores all of the settings on the Sprite.
If you use the Sprite class, you must use Sprite.draw() instead of SpriteBatch.draw().
In my opinion, you should not use the Sprite class at all. You should write your own game object class that has the exact parameters you need and maybe keeps a reference to a TextureRegion. Then when you draw it using SpriteBatch.draw, you pass all the relevant data for position, rotation, etc. Then you are not having to keep redundant copies of your box2d body data in sync.

Related

Is it possible to test if an arbitrary pixel is modifiable by the shader?

I am writing a spatial shader in godot to pixelate an object.
Previously, I tried to write outside of an object, however that is only possible in CanvasItem shaders, and now I am going back to 3D shaders due rendering annoyances (I am unable to selectively hide items without using the culling mask, which being limited to 20 layers is not an extensible solution.)
My naive approach:
Define a pixel "cell" resolution (ie. 3x3 real pixels)
For each fragment:
If the entire "cell" of real pixels is within the models draw bounds, color the current pixel as per the lower-left (where the pixel that has coordinates that are the multiple of the cell resolution).
If any pixel of the current "cell" is out of the draw bounds, set alpha to 1 to erase the entire cell.
psuedo-code for people asking for code of the likely non-existant functionality that I am seeking:
int cell_size = 3;
fragment {
// check within a cell to see if all pixels are part of the object being drawn to
for (int y = 0; y < cell_size; y++) {
for (int x = 0; x < cell_size; x++) {
int erase_pixel = 0;
if ( uv_in_model(vec2(FRAGCOORD.x - (FRAGCOORD.x % x), FRAGCOORD.y - (FRAGCOORD.y % y))) == false) {
int erase_pixel = 1;
}
}
}
albedo.a = erase_pixel
}
tl;dr, is it possible to know if any given point will be called by the fragment function?
On your object's material there should be a property called Next Pass. Add a new Spatial Material in this section, open up flags and check transparent and unshaded, and then right-click it to bring up the option to convert it to a Shader Material.
Now, open up the new Shader Material's Shader. The last process should have created a Shader formatted with a fragment() function containing the line vec4 albedo_tex = texture(texture_albedo, base_uv);
In this line, you can replace "texture_albedo" with "SCREEN_TEXTURE" and "base_uv" with "SCREEN_UV". This should make the new shader look like nothing has changed, because the next pass material is just sampling the screen from the last pass.
Above that, make a variable called something along the lines of "pixelated" and set it to the following expression:
vec2 pixelated = floor(SCREEN_UV * scale) / scale; where scale is a float or vec2 containing the pixel size. Finally replace SCREEN_UV in the albedo_tex definition with pixelated.
After this, you can have a float depth which samples DEPTH_TEXTURE with pixelated like this:
float depth = texture(DEPTH_TEXTURE, pixelated).r;
This depth value will be very large for pixels that are just trying to render the background onto your object. So, add a conditional statement:
if (depth > 100000.0f) { ALPHA = 0.0f; }
As long as the flags on this new next pass shader were set correctly (transparent and unshaded) you should have a quick-and-dirty pixelator. I say this because it has some minor artifacts around the edges, but you can make scale a uniform variable and set it from the editor and scripts, so I think it works nicely.
"Testing if a pixel is modifiable" in your case means testing if the object should be rendering it at all with that depth conditional.
Here's the full shader with my modifications from the comments
// NOTE: Shader automatically converted from Godot Engine 3.4.stable's SpatialMaterial.
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,unshaded;
//the size of pixelated blocks on the screen relative to pixels
uniform int scale;
void vertex() {
}
//vec2 representation of one used for calculation
const vec2 one = vec2(1.0f, 1.0f);
void fragment() {
//scale SCREEN_UV up to the size of the viewport over the pixelation scale
//assure scale is a multiple of 2 to avoid artefacts
vec2 pixel_scale = VIEWPORT_SIZE / float(scale * 2);
vec2 pixelated = SCREEN_UV * pixel_scale;
//truncate the decimal place from the pixelated uvs and then shift them over by half a pixel
pixelated = pixelated - mod(pixelated, one) + one / 2.0f;
//scale the pixelated uvs back down to the screen
pixelated /= pixel_scale;
vec4 albedo_tex = texture(SCREEN_TEXTURE,pixelated);
ALBEDO = albedo_tex.rgb;
ALPHA = 1.0f;
float depth = texture(DEPTH_TEXTURE, pixelated).r;
if (depth > 10000.0f)
{
ALPHA = 0.0f;
}
}

Moving one end of a Phaser.Graphics line

For a project I'm trying to draw a moving line in Phaser. I initially drew it using game.debug.geom(line), but that is not really the right way to do it, since it doesn't allow for styling, and because the debugger takes a toll in performance.
Reading the docs, it seems to me that the way to do it would be with a Phaser.Graphics object, but I haven't been able to get it to work. As an example, I tried making a line move as the hand of a clock, with one end fixed and the other moving around it.
I thought it would be fine to create the Graphics object in the middle and then in update use reset to clear it and bring it back to the center, and then lineTo to make the rest of the line. But instead what I get is a line coming outwards from the centre, and then a ring.
Picture for sadness:
I made a pen with my attempts. The code is repeated below. What I would like to have is a line (lines?) coming from the center of the circle to the points in the circumference.
Is a Graphics object the best way to do that? How do I do it?
Demo.prototype = {
create: function() {
this.graphics = game.add.graphics(
game.world.centerX,
game.world.centerY
);
this.graphics.lineStyle(2, 0xffd900);
this.counter = 0;
this.step = Math.PI * 2 / 360;
this.radius = 80;
},
update: function() {
this.graphics.reset(
this.game.world.centerX,
this.game.world.centerY
);
var y = this.radius * Math.sin(this.counter);
var x = this.radius * Math.cos(this.counter);
this.graphics.lineTo(x, y);
this.counter += this.step;
}
};
You may want to check out this Phaser game called Cut It (not my game btw, found it here).
It also draws a variable length dotted line by cleverly using the Phaser.TileSprite, and then changing its width.
TileSprite draws a repeating pattern, and you can use this to draw a line by drawing one bitmap of a linepart segment, use that as background of the TileSprite and make the height of the TileSprite the same as the height of the bitmap.
You can take a look at the game's source code, it's compressed and minified but still somewhat readable. You can look for the variable called cut_line.
I finally understood that the coordinates taken by the Phaser.Graphics object are local, respective to the object's internal coordinate system. Using moveTo(0, 0) has the desired result of moving the object's drawing pointer back to its origin (and not, as I initially thought, to the origin of the game world). Using reset(0, 0), on the other hand, would have the effect of moving the object's origin to the world's origin.
As for deleting the previous lines, the only method I've found is to manually clear the object's graphicsData Array (short of calling destroy() and creating an entirely new object, which is probably not a very good idea).
Replacing the code in the original question with this does the trick:
Demo.prototype = {
create: function() {
this.graphics = game.add.graphics(
game.world.centerX,
game.world.centerY
);
this.graphics.lineStyle(2, 0xffd900);
this.counter = 0;
this.step = Math.PI * 2 / 360;
this.radius = 80;
},
update: function(){
// Erases the previous lines
this.graphics.graphicsData = [];
// Move back to the object's origin
// Coordinates are local!
this.graphics.moveTo( 0, 0 );
var y = this.radius * Math.sin(this.counter);
var x = this.radius * Math.cos(this.counter);
this.graphics.lineTo(x, y);
this.counter += this.step;
}
};

Arc menu item style like in tumblr app for Android

I tweaked https://github.com/daCapricorn/ArcMenu library to make it work from my purpose and that is working fine. Is there anyway I can build a menu like as in tumblr app or is it possible by tweaking the ArcMenu project or https://github.com/siyamed/android-satellite-menu ? I have doubts on the mathematical functions to be applied to create the style.
I am looking for a animation similar to tumblr app's animation.
try to use , Arc Menu
implement RayMenu and modify RayLayout
and modify the private static AnimationcreateExpandAnimation()` method with your specific coordinate.
There are many ways I do this in iOS. In iOS we have Views similar to that of Android and we can specify coordinates (frame of view) to place them in their superview.
Assumptions :
1)Assume you have a locus i.e circle with equation x^2 + y^2 = c
( Hint : All views are on this locus i.e center of all views coincide with this circle)
2) You need select a value of C depending on the curve you need and initial point which is
(0,HEIGHT_OF_SCREEN) as stating point for placing views.
Algorithm :
int angularDisplacementBetweenEachView = 10; // distance between two views in radians
// coordinates of X button in your screen
int startPositionOfViewX = 0;
int startPositionOfViewY = HEIGHT_OF_SCREEN;
// constant to decide curve
int C = 125;
-(void) main (){ // this is generally done in view controller
for(int i = 1; i< menu_items.count; i++){
Rect position = getCoordinatesForView(menu_item.get(i),menu_item.get(i-1).rect.x,menu_item.get(i-1).rect.y);
addView(menu_item.get(i),position.x,position.y);
}
}
// method returns the coordinates (x,y) at which the view is required to be
//placed.
-(Rect)getCoordinatesForView(View currentView, int prevViewX, int prevViewY){
// convert to polar cordinates
// refer diagram
// this is also the radius of the virtual circle
float r = sqrt(pow(x,2),pow(y,2));
float theta = atan(y,x);
//r & theta are polar coordinates of previous menu item
float theta2 = (angularDisplacementBetweenEachView + r*theta)/r;
// convert back to cartesian coordinates
int x2 = r * cos (theta);
int y2 = r * sin (theta);
return new rect(x2,y2);
}
try this for Arc menu. u can use this sattelite menu
https://github.com/ketanpatel25/android-satellite-menu-center

OpenTK circle rotation

I'm working on my first project using openTk. I'm creating virtual arcball for 3D model rotation. It works fine, but I need to add circle which won't rotate with model. This circle should visualize arcball.
My code to achieve rotation is:
private void SetCamera()
{
GL.MatrixMode(MatrixMode.Modelview);
Matrix4 scale = Matrix4.Scale(magnification / diameter);
Matrix4 translation1 = Matrix4.CreateTranslation(-center);
Matrix4 rotation = Matrix4.CreateFromAxisAngle(axisOfRotation, angleOfRotation*(float)numericSensitivity.Value);
Matrix4 translation2 = Matrix4.CreateTranslation(0.0f, 0.0f, -1.5f);
if (rotationChanged)
{
oldRotation *= rotation;
rotationChanged = false;
}
modelview = translation1 * scale * oldRotation * translation2;
GL.LoadMatrix(ref modelview);
}
So I would like to ask if there is some way how to draw circle, which wil be unaffected by this rotattion (will be on same position on a screen).
If I understand your question correctly, then all you need to do is set the modelview matrix back to the identity before you draw your circle. You can easily do that using the PushMatrix() and PopMatrix() functions. Something like this:
//Draw normal things
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
//Draw un-rotated circle
GL.PopMatrix();
PushMatrix() saves the current matrix onto a stack, and PopMatrix() pops the top matrix off of that stack. This means PopMatrix() will take you back to your normal rotated frame of reference after you're done with the circle.

Using ShowTextAtPoint the displayed text is flipped

I'm using the ShowTextAtPoint method of CGContext to display a Text in a view, but it is displayed in flip mode, anyone knows how to solve this problem ?
Here is the code I use :
ctx.SelectFont("Arial", 16f, CGTextEncoding.MacRoman);
ctx.SetRGBFillColor(0f, 0f, 1f, 1f);
ctx.SetTextDrawingMode(CGTextDrawingMode.Fill);
ctx.ShowTextAtPoint(centerX, centerY, text);
You can manipulate the current transformation matrix on the graphics context to flip it using ScaleCTM and TranslateCTM.
According to the Quartz 2D Programming Guide - Text:
In iOS, you must apply a transform to the current graphics context in order for the text to be oriented as shown in Figure 16-1. This transform inverts the y-axis and translates the origin point to the bottom of the screen. Listing 16-2 shows you how to apply such transformations in the drawRect: method of an iOS view. This method then calls the same MyDrawText method from Listing 16-1 to achieve the same results.
The way this looks in MonoTouch:
public void DrawText(string text, float x, float y)
{
// the incomming coordinates are origin top left
y = Bounds.Height-y;
// push context
CGContext c = UIGraphics.GetCurrentContext();
c.SaveState();
// This technique requires inversion of the screen coordinates
// for ShowTextAtPoint
c.TranslateCTM(0, Bounds.Height);
c.ScaleCTM(1,-1);
// for debug purposes, draw crosshairs at the proper location
DrawMarker(x,y);
// Set the font drawing parameters
c.SelectFont("Helvetica-Bold", 12.0f, CGTextEncoding.MacRoman);
c.SetTextDrawingMode(CGTextDrawingMode.Fill);
c.SetFillColor(1,1,1,1);
// Draw the text
c.ShowTextAtPoint( x, y, text );
// Restore context
c.RestoreState();
}
A small utility function to draw crosshairs at the desired point:
public void DrawMarker(float x, float y)
{
float SZ = 20;
CGContext c = UIGraphics.GetCurrentContext();
c.BeginPath();
c.AddLines( new [] { new PointF(x-SZ,y), new PointF(x+SZ,y) });
c.AddLines( new [] { new PointF(x,y-SZ), new PointF(x,y+SZ) });
c.StrokePath();
}

Resources