I want to implement a game loop (that is acting as a server) in Erlang, but I dont know how to deal with the lack of incrementing variables.
What I want to do, described in Java code:
class Game {
int posX, posY;
int wall = 10;
int roof = 20;
public void newPos(x,y) {
if(!collision(x,y)) {
posX = x;
posY = y;
}
}
public boolean collision(x,y) {
if(x == wall || y == roof) {
// The player hit the wall.
return true;
}
return false;
}
public sendStateToClient() {
// Send posX and posY back to client
}
public static void main(String[] args) {
// The game loop
while(true) {
// Send current state to the client
sendStateToClient();
// Some delay here...
}
}
}
If the client moves, then the newPos() function is called. This function changes some coordinate variables if a collision do not occur. The game loop is going on forever and is just sending the current state back to the client so that the client can paint it.
Now I want to implement this logic in Erlang but I dont know where to begin. I can't set the variables posX and posY in the same way as here... My only thaught is some kind of recursive loop where the coordinates is arguments, but I don't know if that is the right way to go either...
Your intuition is correct: a recursive loop with the state as a parameter is the standard Erlang approach.
This concept is often abstracted away by using one of the server behaviors in OTP.
Simple example, may contain errors:
game_loop(X, Y) ->
receive
{moveto, {NewX, NewY}} ->
notifyClient(NewX, NewY),
game_loop(NewX, NewY)
end.
Related
how can I know the new candle in mql4 is starting?
what is the volume amount of the starting candle? ( starting candle means candle[0])
which of the following codes is true?
a) volume[0]==0
a) volume[0]<0
b) volume[0]<1
c) volume[0]<=1
It's not a good idea to use Volume[0]
Use this code :
void OnTick()
{
static datetime NewBar = 0;
if(NewBar!=Time[0])
{
//do something...
Newbar = Time[0];
}
}
In Dropwizard there is something like meter:
https://metrics.dropwizard.io/3.1.0/getting-started/#meters
It lets me measure rate of events just by invoking mark() method on the metric.
How can I do that in Micrometer?
I can use timers, but I don't want to pass Timer.Sample object to wherever place where I need to call stop() method.
The other missing thing in Micrometer comparing to Dropwizard is a metric that can contain a text message, like gauge in Dropwizard.
Micrometer leverages the strengths of modern metrics backends. So the specific answer to your question depends on which you are using. Take Prometheus for example. The backend can calculate the rate for you.
If you are measuring the rate of how often something is happening you can determine that using a Counter. Take the logback_events_total counter as an example. It is merely counting the number for log messages written.
When alerting or graphing you can then write a query like rate(logback_events_total[1m]) and you will be able to see the rate at which logs have been writen at the 1m rate. You have the ability to change to window from 1m, to 5m or 1h without changing the code.
Regarding text based metrics, those aren't useful for alerting (but can be useful when using a join clause). The typical solution in that case is to create a gauge with a value of 1 or 0 and make your text value a tag. For example:
registry.gaugle('app.info', Tags.of("version","1.0.beta3", this, () -> 1.0));
We had the same problem. In DropWizard we were able to use meters to get the rate of events per minute, but in Micrometer we could not find a built-in way that worked for us.
We needed rates for counters and percentiles for timers. The PrometheusMeterRegistry gave us percentiles, but no rates.
So we built our own Gauge that tracks a Counter. Every time getValue() is called, it fetches the value from the counter and adds it to the right bucket with the current timestamp. Then from all available measurements it can compute the rate over the last minute.
It looks like this:
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import java.util.LinkedList;
import java.util.function.Supplier;
public class OneMinuteRateGauge {
private static final int WINDOW_SECONDS = 60;
private final Supplier<Double> valueSupplier;
private final LinkedList<Bucket> buckets;
private final Clock clock;
public OneMinuteRateGauge(String name, Supplier<Double> valueSupplier, MeterRegistry meterRegistry) {
this(name, valueSupplier, meterRegistry, Clock.SYSTEM);
}
public OneMinuteRateGauge(String name, Supplier<Double> valueSupplier, MeterRegistry meterRegistry, Clock clock) {
this.valueSupplier = valueSupplier;
this.buckets = new LinkedList<>();
Gauge.builder(name, this::getValue).register(meterRegistry);
this.clock = clock;
// Collect one measurement so we have a faster start
getValue();
}
public synchronized double getValue() {
// Update the last bucket or create a new one
long now_millis = clock.monotonicTime() / 1_000_000;
long now_seconds = now_millis / 1_000;
short millis = (short) (now_millis - (now_seconds * 1000));
double value = valueSupplier.get();
if (buckets.size() != 0 && buckets.getLast().getSeconds() == now_seconds) {
buckets.getLast().updateValue(millis, value);
} else {
buckets.addLast(new Bucket(now_seconds, millis, value));
}
// Delete all buckets outside the window except one
while (2 < buckets.size() && buckets.get(1).getSeconds() + WINDOW_SECONDS < now_seconds) {
buckets.pollFirst();
}
if (buckets.size() == 1) {
// Not enough data
return 0;
} else if (now_seconds <= buckets.getFirst().getSeconds() + WINDOW_SECONDS) {
// First bucket is inside the window
return buckets.getLast().getValue() - buckets.getFirst().getValue();
} else {
// Find the weighted average between the first two points
Bucket p0 = buckets.get(0);
Bucket p1 = buckets.get(1);
double px = now_millis - (WINDOW_SECONDS * 1000);
double m = (p1.getValue() - p0.getValue()) / (p1.getTimestampInMillis() - p0.getTimestampInMillis());
double py = m * (px - p0.getTimestampInMillis()) + p0.getValue();
return value - py;
}
}
}
public class Bucket {
private long seconds; // Seconds since 1.1.1970, used as bucket ID
private short millis; // 0-999, used for a more exact calculation
private double value;
public Bucket(long seconds, short millis, double value) {
this.seconds = seconds;
this.millis = millis;
this.value = value;
}
public long getSeconds() {
return seconds;
}
public double getValue() {
return value;
}
public long getTimestampInMillis() {
return seconds * 1000 + millis;
}
public void updateValue(short millis, double value) {
this.millis = millis;
this.value = value;
}
}
An alternative way could have been to use CompositeMeterRegistry on the top level and then add both a PrometheusMeterRegistry and a StepMeterRegistry. Prometheus reports percentiles and Step reports rates. Our monitoring system would then have to query two endpoints.
This was a temporary solution until we modified our monitoring system to read the prometheus endpoint and calculate its own rates.
Is it possible to have a mouse event be called for two sprites overlapping? I have attempted to use getObjectsUnderPoint however it does not seem to be working.
class Line extends Sprite
{
int x;
int y;
int type;
var tempLine = new Shape();
bool isClicked = false;
Line(int xPos, int yPos, int type)
{
this.x = xPos;
this.y = yPos;
this.type = type;
if(type == 1)
{
graphics.beginPath();
graphics.moveTo(x, y);
graphics.lineTo(x+300, y);
graphics.closePath();
graphics.strokeColor(Color.LightGray,19);
addEventListener(MouseEvent.CLICK, react);
tempLine.graphics.beginPath();
tempLine.moveTo(x,y);
tempLine.graphics.lineTo(x+300,y);
tempLine.graphics.closePath();
}
else if(type == 2)
{
graphics.beginPath();
graphics.moveTo(x, y);
graphics.lineTo(x, y+300);
graphics.closePath();
graphics.strokeColor(Color.LightGray,19);
addEventListener(MouseEvent.CLICK, react);
tempLine.graphics.beginPath();
tempLine.moveTo(x,y);
tempLine.graphics.lineTo(x,y+300);
tempLine.graphics.closePath();
}
addChild(tempLine);
}
react(MouseEvent event)
{
Point tempPoint = new Point(event.localX, event.localY);
graphics.strokeColor(Color.Black,19);
isClicked = true;
var subShape = getObjectsUnderPoint(tempPoint);
for(Shape i in subShape)
{
i.parent.userData.isClicked = true;
}
}
}
I have two Line objects overlapping and when one is clicked I want the boolean for both objects to be true. I have read that the getObjectsUnderPoint does not return a Sprite, could this be the issue?
MouseEvents are only dispatched to the top most display object that extends the InteractiveObject class (which is true for all DisplayObjectContainers and Sprites). So only one display object can receive the MouseEvent.CLICK event. You are right that the getObjectsUnderPoint does only return the children of DisplayObjectContainers but there is an open issue on the GitHub repository (https://github.com/bp74/StageXL/issues/209) talking about this. One of the next versions of StageXL (greater than version 0.13) may change this behavior.
I am using mapField to create a custom map.I am using the code in this link.
How to show more than one location in Blackberry MapField?.
But the map position is fixed. i am not able to drag the map as we can do in google maps or when we invoke the maps like
public void execute(ReadOnlyCommandMetadata metadata, Object context)
{
Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, new MapsArguments());
}
Here's some code that should get you going on the correct path. I've taken it from a project of mine that had some special requirements, so there could be some remnants of that left in there inadvertently. There will be some undefined variables in there -- they're member variables that are declared in the class and should all start with an underscore. This is also part of a class that extends MapField, so you would have to create a custom map class and then use that rather than the default.
protected boolean touchEvent(TouchEvent message) {
boolean ret = super.touchEvent(message);
//mark that we're starting to interact
if(message.getEvent() == TouchEvent.DOWN) {
_startTouchTracking = true;
_clicking = true;
_touchX = message.getX(1);
_touchY = message.getY(1);
}
//user is wanting to move the map
else if(message.getEvent() == TouchEvent.MOVE) {
int dx = _touchX - message.getX(1);
int dy = _touchY - message.getY(1);
_clicking = false;
_touchX = message.getX(1);
_touchY = message.getY(1);
//perform checks to make sure we don't move outside of the map's range
int lat = getLatitude() - dy*(int)MathUtilities.pow(2, (double)getZoom());
if(lat < -9000000) {
lat = -9000000;
}
else if (lat > 9000000) {
lat = 9000000;
}
int lon = getLongitude() + dx*(int)MathUtilities.pow(2, (double)getZoom());
if(lon < -18000000) {
lon = -18000000;
}
else if (lon > 18000000) {
lon = 18000000;
}
moveTo(lat, lon);
}
//if the person just touches and releases, we want to move to that spot
else if (message.getEvent() == TouchEvent.UNCLICK && _clicking) {
int dx = message.getX(1) - getWidth()/2;
int dy = message.getY(1) - getHeight()/2;
move(dx, dy);
_clicking = false;
}
//touch has been released
else if (message.getEvent() == TouchEvent.UP) {
_startTouchTracking = false;
}
//we handled the click
return true;
}
As said, this might need tweaking for your use, but in general should get you started. The MathUtilities.pow() calls were my way of coming up with an appropriate amount of motion depending on the zoom level.
Edit for Comments
Letting a Bitmap move with the map:
protected Coordinates _bitmapCoordinates;
protected Bitmap _bitmap;
public YourMapField() {
//we're going to put the bitmap at -38.43, 20.32
_bitmapCoordinates = new Coordinates(-38.43, 20.32, 0.0);
_bitmap = YOUR_CODE_TO_GET_THE_BITMAP;
}
protected void paint(Graphics g) {
super.paint(g);
XYPoint placeToPaintBitmap = new XYPoint();
convertWorldToField(_bitmapCoordinates, placeToPaintBitmap);
//perform a check here to make sure that field will be seen. This code would depend
//on how you're painting the image. Just check the placeToPaintBitmap.x and placeToPaintBitmap.y
//against 0 and the map's width and height, along with some adjustment for how you paint
if(bitmap will be visible on the screen) {
//The code I have here is drawing the bitmap from the top left of the image, but if
//you need to draw from some other place you may have to offset the x and y
g.drawBitmap(placeToPaintBitmap.x, placeToPaintBitmap.y, _bitmap.getWidth(), _bitmap.getHeight(), 0, 0);
}
}
I didn't test any of that code, so it might be buggy but should give you the general idea.
I'm trying to figure out how to manage the whole game loop manually in a Windows game, without using the regular Game Microsoft.Xna.Framework.Game class.
The reason for this is using the regular Game class causes some stuttering in my game. Not much, but because of the specific nature of the game it is still quite visible.
After trying a bunch of different settings (vsync, fixedtimestep, various framerates etc.) I decided to try write my own Game class to have full control of the timing. I am not sure that will fix it, but at least this way I have full control.
Basically I need to:
Set up the game window
In a loop: Do all rendering as usual, and then flush the result to the screen, manage backbuffers etc.
Anyone knows how to do this? It sounds quite easy in fact, but could not find any documentation on how to do it.
Not sure what I am doing wrong, but I have the following code (just for testing, timing will be handled differently), and the loop will run for a little while then stop. Once I pass my mousepointer over the window the loop will run for a little while again.
private void Application_Idle(object pSender, EventArgs pEventArgs)
{
Thread.Sleep(500);
//Message message;
//while (!PeekMessage(out message, IntPtr.Zero, 0, 0, 0))
{
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
}
If enabling the "while PeekMessage", the loop will run continuously, but ignoring the sleep and also stopping when the mouse is moving over the window. Not sure what is going on here...
I think optimally I would just want to do something simple like this in the main render loop:
while (alive)
{
Thread.Sleep(100);
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
But in this case the window remains blank, as it seems the window is not actually being redrawn with the new content. I tried a form.Refresh(), but still no go... Any ideas?
(added xbox information)
for windows you Basically need to create a Form and Show it, then store its handle and the form itself.
Using this handle you can create a GraphicsDevice.
Then you hook Application.Idle to your own function that calls your update and render.
For example
public class MyGame
{
public Form form;
public GraphicsDevice GraphicsDevice;
public MyGame()
{
form = new Form();
form.ClientSize = new Size(1280, 1024);
form.MainMenuStrip = null;
form.Show();
}
public void Run()
{
PresentationParameters pp = new PresentationParameters();
pp.DeviceWindowHandle = form.Handle;
pp.BackBufferFormat = SurfaceFormat.Color;
pp.BackBufferWidth = 1280;
pp.BackBufferHeight = 1024;
pp.RenderTargetUsage = RenderTargetUsage.DiscardContents;
pp.IsFullScreen = false;
pp.MultiSampleCount = 16;
pp.DepthStencilFormat = DepthFormat.Depth24Stencil8;
GraphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter,
GraphicsProfile.HiDef,
pp);
Application.Idle += new EventHandler(Application_Idle);
Application.Run(form);
}
private void Application_Idle(object pSender, EventArgs pEventArgs)
{
Message message;
while (!PeekMessage(out message, IntPtr.Zero, 0, 0, 0))
{
/* Your logic goes here
Custom timing and so on
Update();
Render();
*/
}
}
void Render()
{
GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.Black, 1, 0);
//Your logic here.
GraphicsDevice.Present();
}
[StructLayout(LayoutKind.Sequential)]
private struct Message
{
public IntPtr hWnd;
public int msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public Point p;
}
[return: MarshalAs(UnmanagedType.Bool)]
[SuppressUnmanagedCodeSecurity, DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint
messageFilterMin, uint messageFilterMax, uint flags);
}
EDIT 1
For xbox you may just be able to place your own custom run function with your game loop in a throttled while true loop. Inside that run outside the top of the while true you will probably have to do the graphics device initialization and verification with IntPtr.Zero as your handle
EDIT 2
i use something like this ( got from http://www.koonsolo.com/news/dewitters-gameloop/ )
private long nextGameTick;
private Stopwatch stopwatch;
const int ticksPerSecond = 60;
const int skipTicks = 1000 / ticksPerSecond;
private const int maxSkip = 10;
`constructor
stopwatch = Stopwatch.StartNew();
nextGameTick = stopwatch.ElapsedMilliseconds;
`loop
int loops = 0;
long currentTick = stopwatch.ElapsedMilliseconds;
while ( (ulong)(currentTick - nextGameTick) > skipTicks && loops < maxSkip)
{
Update(16.667f);
nextGameTick += skipTicks;
loops++;
}
PreRender();
Render();
PostRender();
EDIT 3
Creating a content manager was a little more work, but still managable. You need to create a class that implements IServiceProvider. This class takes a GraphicsDevice in its constructor in order to create the next class the implements IGraphicsDeviceProvider. in addition I implement GetService like this
//in implementer of IServiceProvider
public object GetService ( Type serviceType )
{
if ( serviceType == typeof ( IGraphicsDeviceService ) )
{
return myGraphicsService;
}
return null;
}
For convenience i also add a method to the class to create and return managers
//in implementer of IServiceProvider
public ContentManager CreateContentManager( string sPath )
{
ContentManager content = new ContentManager(this);
content.RootDirectory = sPath;
return content;
}
In addition i create a class that implements IGraphicsDeviceService and takes a reference to my GraphicsDevice. then I create a property and field in it like so
//in implementer of IGraphicsDeviceService
private GraphicsDevice graphicsDevice;
public GraphicsDevice GraphicsDevice
{
get
{
return graphicsDevice;
}
}
So the call ends up being somehting like
MyServiceProvider m = new MyServiceProvider(graphicsDevice);
ContentManager content = m.CreateContentManager("Content");
where
MyServiceProvider(GraphicsDevice graphicsDevice)
{
myGraphicsService = new MyGraphicsDeviceService(graphicsDevice);
}
MyGraphicsDeviceService(GraphicsDevice gfxDevice)
{
graphicsDevice = gfxDevice;
}
-Sorry for fragmenting the code around but its not something i wrote too recently so im having difficulty remembering parts.
EDIT 4
i had an odd case with my custom game i just remembered when i new the Form for it i
had to bind
private void IgnoreAlt(object pSender, KeyEventArgs pEventArgs)
{
if (pEventArgs.Alt && pEventArgs.KeyCode != Keys.F4)
pEventArgs.Handled = true;
}
to
form.KeyUp += IgnoreAlt;
form.KeyDown += IgnoreAlt;
otherwise i got some horrible stalls.