Show Posts

You can view here all posts made by this member. Note that you can only see posts made in areas to which you currently have access.

Messages - Snarky

Pages: [1] 2 3 ... 202
Critics' Lounge / Re: Up scaleing pixel background
« on: Yesterday at 17:06 »
That looks much better overall! However, when you look closer the mix of high-resolution and low-resolution regions becomes very noticeable, and the image as a whole looks rather unfinished.

I'm afraid there isn't a cheap, quick way to upscale low-resolution pixel art to vector graphics with consistently good results, but I would at least try to get rid of the "jaggies", maybe by running a Median filter over the pixelated parts of the image (or just use the vectorized version instead). And if you're not going to paintover the entire screen, I wouldn't add so much detail in some parts (e.g. grass texture on the plain, or so much work on the rocks). I think the look of the sky or the far hills on the right are a better compromise.

I use Avast too, and I often get a popup when I have a new AGS game and the virus shield scans it. But in my experience it always lets it through eventually, I just have to wait a minute or two for the scan to complete.

Yes, congrats Myinah, and hope you'll enjoy the job! It's great that there'll be AGS talent behind this title. The way Gilbert and Winick are building up the team and raising the quality level on the stuff they're previewing is going a long way to address some of the concerns I had at the start of the project; I'm happy I ended up backing it.

Yes, your thinking is more or less right, that's how you'd want to do it. You wouldn't have different properties for each hotspot, though. Rather, you'd have one property with different VALUES depending on which cursor you want.

The AGS syntax for this looks something like:

Code: Adventure Game Studio
  1. // Here's how you get the "Cursor" property of the current hotspot
  2. Hotspot* activeHotspot = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
  3. int hotspotCursor = -1;
  4. if(activeHotspot != null)
  5.   hotspotCursor = activeHotspot.GetProperty("Cursor");
  7. // And here's how you use it to set the cursor
  8. if(hotspotCursor == 1)
  9.   mouse.Mode = eModeLookAt;
  10. else if(hotspotCursor == 2)
  11.   mouse.Mode = eModeInteract;
  12. // etc.

I also noticed it, and I'm no audio engineer (but I was listening with earbuds).

The game looks great, but I wasn't so keen on the music in the trailer: there were some weird rhythm changes and odd notes mixed in that kept throwing me off. Maybe it will work better in-game.

Here's some math to calculate the result of a collision between two balls, based on the link above. First, let's do the case where one ball (A) is at rest, and is hit by the other (B).

First we work out how the balls hit each other, by taking the vector between the centers of the balls:

Code: Adventure Game Studio
  1. float dx = A.position_x - B.position_x;
  2. float dy = A.position_y - B.position_y;

Then we calculate the angle between this vector and the movement of B, using the formula for the angle between two vectors u and v: cos(theta) = dotproduct(u,v)/(length(u)*length(v))

Code: Adventure Game Studio
  1. float dotprod = B.velocity_x*dx + B.velocity_y*dy;
  2. float velocity_length = Maths.Sqrt(B.velocity_x*B.velocity_x + B.velocity_y*B.velocity_y);
  3. float dist_length = Maths.Sqrt(dx*dx + dy*dy);
  4. float theta = Maths.ArcCos(dotprod/(velocity_length*dist_length));

(Note that this theta is not the same as in the diagrams on the web page, but perpendicular to it.)
Now if theta is 0, we hit the ball straight on, and it's very simple: the movement of B just gets transferred to A, and B stops:

Code: Adventure Game Studio
  1. if(theta == 0.0)
  2. {
  3.   A.velocity_x = B.velocity_x;
  4.   A.velocity_y = B.velocity_y;
  5.   B.velocity_x = 0;
  6.   B.velocity_y = 0;
  7. }

If theta is not 0, we hit it at an angle, and they'll both glance off each other. As explained here, the angles are parallel and perpendicular to the angle between the balls at the point of collision: (dx,dy) for A and (dy,-dx) for B, because reasons, and the magnitudes are such that the vectors form a right-angled triangle with the initial velocity of B. That means that we can calculate the magnitudes using sin and cos:

Code: Adventure Game Studio
  1. else
  2. {
  3.   A.velocity_x =  dx * Maths.Cos(theta) * velocity_length / dist_length;
  4.   A.velocity_y =  dy * Maths.Cos(theta) * velocity_length / dist_length;
  5.   B.velocity_x =  dy * Maths.Sin(theta) * velocity_length / dist_length;    // TODO: Check what happens if theta < 0. (Wrong sign, so direction is possibly flipped?)
  6.   B.velocity_y = -dx * Maths.Sin(theta) * velocity_length / dist_length;
  7. }

To do two moving balls, I would just change the frame of reference to one where ball A is at rest for our calculations (subtract the velocity of ball A from the velocity vectors at the start, and add it back at the end):

Code: Adventure Game Studio
  1. float vA_x = A.velocity_x;
  2. float vA_y = A.velocity_y;
  4. // Subtract the velocity of A
  5. A.velocity_x = 0.0;
  6. A.velocity_y = 0.0;
  7. B.velocity_x -= vA_x;
  8. B.velocity_y-= vA_y;
  10. // Do all the other stuff here
  11. // ...
  13. // Add the velocity of A back
  14. A.velocity_x += vA_x;
  15. A.velocity_y += vA_y;
  16. B.velocity_x += vA_x;
  17. B.velocity_y += vA_y;

These calculations could be optimized by a lot, by the way (instead of calculating theta with arccos, just calculate cos(theta), only calculate velocity_length/dist_length once, etc.), but I wanted to keep it as close as possible to the logic of the problem for clarity. I haven't tested any of this, so there might be mistakes in the math or the code.

Why don't you just try it?

when the mouse mode updates 40 times a second?
at 40 times a second you'de never notice (faster than the eye) ;)

This is not true. If the cursor were to change shape (or disappear) for one frame, it would certainly be noticeable at 40 fps, unless the change was very subtle. You'd probably see it as a brief flicker.

Here's a sketch of the logic I would use. This is by no means complete, and is untested. Barring bugs, it should be able to simulate ball movements with bounces off the bumpers (sides). Ball-to-ball collisions are detected, but the deflections have not been implemented; that would be the next step, followed by pockets (which I'd just do as special-case collisions with "balls" fixed at certain positions).

This is very naive, as it just waits for things to intersect and then changes their direction of movement, so balls will slightly pass through each other and into the bumpers (but that's probably OK, since it has a bit of give). If possible, I would run more than one update per frame: with e.g. ten updates per frame it should be pretty good.

Code: Adventure Game Studio
  1. // Header
  2. #define BALL_COUNT 16 // 8-ball pool (15 balls + white)
  4. enum BallType
  5. {
  6.   eBallStripe,
  7.   eBallColor,
  8.   eBallWhite,
  9.   eBallBlack
  10. };
  12. struct BilliardBall
  13. {
  14.   int id;
  15.   BallType type;
  17.   float position_x;
  18.   float position_y;
  19.   float old_position_x;
  20.   float old_position_y;
  22.   float velocity_x;
  23.   float velocity_y;
  25.   import static void init8Ball();
  26.   import static void updateAll();
  27. };
  29. import BilliardBall billiardBall[BALL_COUNT];
  31. // Script
  32. #define TABLE_TOP 0.0
  33. #define TABLE_BOTTOM 500.0
  34. #define TABLE_LEFT 0.0
  35. #define TABLE_RIGHT 250.0
  37. BilliardBall billiardBall[BALL_COUNT];
  39. float friction_coeff_dyn = 0.999;  // How much of the speed dissipates per tick (1 - this number)
  40. float friction_limit_stat = 0.005; // Minimum movement speed before it stops
  41. float bounce_coeff_bumper = 0.85;  // How much speed is preserved in a bounce off the wall
  42. float radius 5.0;                  // Let's assume all the balls have the same radius (check proportional to table size)
  44. float abs(float f)
  45. {
  46.   if(f<0)
  47.     return -f;
  48.   return f;
  49. }
  51. static void BilliardBall::init8Ball()
  52. {
  53.   int i=0;
  54.   while(i<BALL_COUNT)
  55.   {
  56.     if(i<8)
  57.       billiardBall[i].type = eBallColor;
  58.     else
  59.       billiardBall[i].type = eBallStripe;
  61.     billiardBall[i].id =i;
  62.     i++;
  63.   }
  64.   billiardBall[0].type = eBallWhite;
  65.   billiardBall[8].type = eBallBlack;
  67.   // TODO: Setup initial positions
  68. }
  70. void BilliardBall::moveNaive()
  71. {
  72.   this.old_position_x = this.position_x;
  73.   this.old_position_y = this.position_y;
  75.   this.velocity_x = this.velocity_x * friction_coeff_dyn;
  76.   this.velocity_y = this.velocity_y * friction_coeff_dyn;
  78.   if(this.velocity_x * this.velocity_x + this.velocity_y * this.velocity_y > friction_limit_stat * friction_limit_stat)
  79.   {
  80.     this.position_x = this.this.position_x + this.velocity_x;
  81.     this.position_y = this.position_y + this.velocity_y;
  82.   }
  83.   else
  84.   {
  85.     this.velocity_x = 0.0;
  86.     this.velocity_y = 0.0;
  87.   }
  88. }
  90. // This is very simple & sloppy
  91. static void BilliardBall::checkCollisions()
  92. {
  93.   float d = radius + radius;
  94.   int i=0;
  95.   while(i<BALL_COUNT)
  96.   {
  97.     if( (billiardBall[i].position_x - radius < TABLE_LEFT) || (billiardBall[i].position_x + radius > TABLE_RIGHT) )
  98.     {
  99.       billiardBall[i].velocity_x = -(billiardBall[i].velocity_x * bounce_coeff_bumper);
  100.       billiardBall[i].velocity_y =  (billiardBall[i].velocity_y * bounce_coeff_bumper);
  101.     }
  102.     if( (billiardBall[i].position_y - radius < TABLE_TOP) || (billiardBall[i].position_y + radius > TABLE_BOTTOM) )
  103.     {
  104.       billiardBall[i].velocity_x =  (billiardBall[i].velocity_x * bounce_coeff_bumper);
  105.       billiardBall[i].velocity_y = -(billiardBall[i].velocity_y * bounce_coeff_bumper);
  106.     }
  107.     int j=i+1;
  108.     while(j<BALL_COUNT)
  109.     {
  110.       dX = billiardBall[i].position_x - billiardBall[j].position_x;
  111.       dY = billiardBall[i].position_y - billiardBall[j].position_y;
  112.       // Simple test (hit box)
  113.       if( (abs(dX) < d) && (abs(dY) < d)
  114.       {
  115.         // Accurate test
  116.         if(dX*dX + dY*dY < d*d)
  117.         {
  118.           // TODO: Calculate new velocity vectors, based on
  119.         }
  120.       }
  121.     }
  122.   }
  123. }
  125. static void BilliardBall::updateAll()
  126. {
  127.   int i=0;
  128.   while(i<BALL_COUNT)
  129.   {
  130.     billiardBall[i].moveNaive();
  131.     i++;
  132.   }
  133.   BilliardBall.checkCollisions();
  134. }

Edit: Fixed a couple of bugs

There have been some attempts to implement physics into AGS, so you might be able to build on some of that. Also, I'm sure there's a great deal of documentation of how to do physics engines in general online. But just as a starter:

To do the movement, you definitely want to store velocity vectors for each ball, and keep the positions and velocities as floats that you convert to int just for display purposes. This lets you do friction quite easily, and you could extend it to add spin later on.

To check whether two equal-size balls are colliding, just calculate the pythagorean distance between them, and compare to their radius*2; if smaller, you have a collision. To calculate whether a ball hits the wall, you can just check the x and y coordinates, assuming the table is aligned with the coordinate system.

To work out the angles of reflection given a collision, you need a little bit of trigonometry, and to observe the conservation of momentum. Bouncing off a wall is pretty easy (you just reflect the movement vector by the line of the wall);  I'm not sure off the top of my head how to do the collision between balls, but slasher's link seems to have all the details.

Critics' Lounge / Re: Up scaleing pixel background
« on: 04 Oct 2015, 12:14 »
I don't particularly mind the "look" of the vectorized upscaling, but I do think it's problematic in the loss of some of the detail (check out the moon and stars in the vector version of that last screen, for example).

Also, I would be very worried about performance with a 1280x760 AGS game running on mobile, particularly when your game uses full-screen overlays for snow/rain effects. Have you actually tested it running, or did you just try displaying the backgrounds? Visionaire or some other engine is probably a better bet.

And, no offense: I like Infinity String a lot, but I also wonder whether it be all that well received as a commercial release. The upscaling, the lack of voice acting (unless you spring for that), and some rough edges (grammar and spelling mistakes, for examples)... I think it would take significant work to bring it up to the standard most players expect when they pay money for a game nowadays. And a lot of your potential market have probably already played the freeware version. Maybe I'm completely wrong, but I wouldn't expect to make enough money from it to repay the additional investment.

If you're doing it mainly because you want to realize some improvements you have in mind, then you should of course make the game you want.

Critics' Lounge / Re: Up scaleing pixel background
« on: 03 Oct 2015, 18:11 »
Meanwhile, this is what The Infinity String looks like upscaled with the HQ3X filter that comes built-in with AGS:

Yeah, the vectorized version looks a little better, but by enough to justify a total remake? If you just update to the latest engine version and replace the snow/rain plugin with a module, you'll be able to run it in 1280x720 without any other changes. Do what you want, of course, but I'd be way more excited to hear you're working on a new game.

Part of the reason some prefer a zip (or other archive) file to an exe is a suspicion of blindly running executables downloaded from the internet. Granted, it doesn't make that much sense in this case, since you'll still need to run the AGS exe once the file is unzipped, but I think it would be better to stick with a zip file nevertheless, just for people's ease of mind.

I'm not exactly clear on how it can make a difference whether the CHM file was originally downloaded as a zip and then unzipped, or as a zip.exe and then self-extracted. Does Windows peek into the zip file and add the extra data stream to every file inside, or what? Or is it only if you use windows built-in functionality to extract the file, rather than 7zip/WinZip/WinRar or some other app?

Hey, I hope this works out for you and you find a way to be happier!

If it helps with AGS development, that's also nice. ;)

The Rumpus Room / Re: *Guess the Movie Title*
« on: 02 Oct 2015, 08:39 »
That's the one! (I'd recommend it; it's very funny.)

You worked out the coding solution to switch graphics on your own. I just wanted to mention that if your inventory item sprites are relatively small, it might be possible to generate the grayed-out versions on the fly using DynamicSprites and DrawingSurfaces. (The AGS calls you'd need are pretty slow, but on newer computers with small sprites it might work.)

I'll try to align it to sun as a lightsource.

The moon is aligned, but the shading of the earth really isn't (it implies a sun in the top-right corner-ish, and since the sun is way off in the distance, far more of the planet should be in shadow, which should also be darker, just like with the moon). Also, if we're at all concerned with astronomical accuracy, the axis of the earth looks tilted way off (though that might have something to do with the huge tree growing out of it), particularly when you remember that the earth, sun and moon are all more or less in the same plane (the ecliptic, which is why you regularly get eclipses like on Monday morning). Basically, if you just rotate the earth so that the shading lines up with the position of the sun, it would be more or less accurate.

I'm also very interested, but wouldn't be able to go in the (NH) spring; late 2016 is a much better possibility.

The Rumpus Room / Re: *Guess the Movie Title*
« on: 30 Sep 2015, 21:57 »
I grant the resemblance to Nicole Kidman is uncanny, but no.

The Rumpus Room / Re: *Guess the Movie Title*
« on: 30 Sep 2015, 20:15 »
Spoilered because it's JUST TOO SEXY!

The Rumpus Room / Re: *Guess the Movie Title*
« on: 30 Sep 2015, 19:11 »
Oh, I know: Coherence!

Pages: [1] 2 3 ... 202