Slick2D - Same movement on every computer - time

I am coding a game with friends and we have problems to get the same movement on our different PC. In Slick2D, we use the Delta to make the movement :
if (input key up)
{
sprite = up; // changing the sprite
if (no collision){
sprite.update(delta*3); //animation
y -= delta * 0.3f; // movement
}
}
The problem is that delta is the time between two frames. And this time in not the same on each computer because of performance. So the slower the computer is, the slower the movement will be.
How to solve this problem ?
Thank you for helping us, and I hope you understand my english !

How about setting a target frame rate for your application? It can normalize the speed of movement throughout all computers (given the computer can reach that rate). So whenever you first instantiate your game class, do this:
private static final int TARGET_FRAME_RATE = 60;
private static final int WINDOW_WIDTH = 640;
private static final int WINDOW_HEIGHT = 480;
public static void main(String[] args) {
try {
AppGameContainer appgc = new AppGameContainer(new MyGame());
appgc.setDisplayMode(WINDOW_WIDTH, WINDOW_HEIGHT, false);
// Set the target framerate for the appgc
appgc.setTargetFrameRate(TARGET_FRAME_RATE);
appgc.start();
} catch (SlickException e) {
System.err.println("There was an error executing the game...");
e.printStackTrace();
}
}

Related

Changing the Speed of a motor in Processing/box2D

I've been making some simple games using processing and box2D using The Nature of Code as a resource.
My problem is I have gotten to a point where I have these windmills that go clockwise/counterclockwise depending on the speed of the motor (I am using PI/2 and -PI*2). I want to have it so that the user can change this speed from positive and negative by pressing a key or mouse button. Looking around online people and the box2D documentation are saying to use the function void SetMotorSpeed(float speed);, however I am not having luck figuring out how to implement this. I've tried a few ways I can think but no luck.
Currently I have this in my main file ("s" is the name of the instance of the windmill):
// Click the mouse to switch speed of motor
void mousePressed() {
s.SetMotorSpeed(s.speed);
}
And I have this in the file for the windmill:
//Set Motor Speed
void SetMotorSpeed(float speed){
speed = speed * -1;
}
This doesn't work though.
I'm fairly new to coding and this is my first post on stack-overflow so my apologies if I have done anything wrong in how I'm asking or presenting this question. I'm open to suggestions both code and etiquette wise!
Here is the code for the entire windmill:
class Seesaw {
// object is two boxes and one joint
RevoluteJoint joint;
// float speed = PI*2;
Box box1;
Box box2;
float speed = PI*2;
Seesaw(float x, float y) {
// Initialize locations of two boxes
box1 = new Box(x, y-20, 120, 10, false);
box2 = new Box(x, y, 10, 40, true);
// Define joint as between two bodies
RevoluteJointDef rjd = new RevoluteJointDef();
Vec2 offset = box2d.vectorPixelsToWorld(new Vec2(0, 60));
rjd.initialize(box1.body, box2.body, box1.body.getWorldCenter());
// Turning on a motor (optional)
rjd.motorSpeed = PI*2; // how fast?
rjd.maxMotorTorque = 1000.0; // how powerful?
rjd.enableMotor = true; // is it on?
// Create joint
joint = (RevoluteJoint) box2d.world.createJoint(rjd);
}
// Turn the motor on or off
void toggleMotor() {
joint.enableMotor(!joint.isMotorEnabled());
}
boolean motorOn() {
return joint.isMotorEnabled();
}
void SetMotorSpeed(float speed){
speed = -speed;
}
void display() {
box2.display();
box1.display();
// Draw anchor just for debug
Vec2 anchor = box2d.coordWorldToPixels(box1.body.getWorldCenter());
fill(255, 0, 0);
stroke(0);
ellipse(anchor.x, anchor.y, 4, 4);
}
}
The change in speed should be communicated to the joint. Try this:
void SetMotorSpeed(float speed) {
s.joint.setMotorSpeed(speed); // edited, processing/java uses camel-case
}
you might also be a bit more careful about naming variables. In your original post you use the same name for the local variable and the member variable, which has not the wanted effect. Most people use some naming convention for member variable to avoid this kind of very common error. Like for instance have all member variables all start with "_"
void SetMotorSpeed(float speed) {
_speed = -speed; // speed is local!
}

Enemies always clumping together in unity 2d

I'm trying to make a top-down shooter game in unity 2d. But the enemies are always clumping together. Does someone knows how to avoid it?
Here's my enemy code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float moveSpeed;
public float stoppingDistance;
public Transform player;
private Rigidbody2D rb;
public GameObject effect;
public int health = 3;
public static int enemyCounter;
public SpriteRenderer enemy;
public Color hurtColor;
void Start() {
rb = GetComponent<Rigidbody2D>();
player = GameObject.FindGameObjectWithTag("Player").transform;
}
void Update() {
enemyCounter = EnemySpawner.enemyCounter;
Vector2 direction = transform.position - player.position;
if (Vector2.Distance(transform.position, player.position) > stoppingDistance) {
transform.position = Vector2.MoveTowards(transform.position, player.position,
moveSpeed * Time.deltaTime);
}
else if (Vector2.Distance(transform.position, player.position) > stoppingDistance) {
transform.position = this.transform.position;
}
}
IEnumerator Flash(){
enemy.color = hurtColor;
yield return new WaitForSeconds(0.01f);
enemy.color = Color.red;
}
void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "Bullet") {
StartCoroutine(Flash());
health -= 1;
}
if (health <= 0) {
GameObject DestroyEnemy = Instantiate(effect, transform.position, Quaternion.identity);
Destroy(this.gameObject);
Destroy(DestroyEnemy, 2f);
}
}
}
The enemies is moving towards the player, but they clump together when I move the player. I really need help.
If the enemies are moving in straight line to the player they will always clump up. If you want to ensure a minimal distance between enemies you could consider using a second larger collider on another layer but this will might end up looking bad and could make some exploits possible if too big.
The other alternative would be to change the behaviour of the enemies. Making an enemy move depending on the position of the other enemies seems complicated therefore i would simply try to add some randomness to their behaviour. Here are some ideas you could try:
-(would be my first try) switch randomly between two behaviours, 1: move straight to the player (always if very close to player), 2: move in a random direction (sometimes when further away from the player)
-don't give all your enemies the same speed
-make them move towards the player + a small random angle away from the player if far away
-...
To sum it up you will need an improved behaviour and there isn't a single solution.

Fast moving objects 2D game (Unity3d)

I find the official unity training https://www.youtube.com/watch?v=D5MqLcO6A8g
and find bug.(look at the score)
I spent about 2 days to fix it and failed.
I find the "DontGoThroughThings" script and try to rewrite to use in 2D. Failed again)
Please help me!
This is rewrite script:
public LayerMask layerMask; //make sure we aren't in this layer
public float skinWidth; //probably doesn't need to be changed
private float minimumExtent;
private float partialExtent;
private float sqrMinimumExtent;
private Vector2 previousPosition;
private Rigidbody2D myRigidbody;
//initialize values
void Awake()
{
myRigidbody = GetComponent<Rigidbody2D>();
previousPosition = myRigidbody.position;
minimumExtent = Mathf.Min(Mathf.Min(GetComponent<Collider2D>().bounds.extents.x, GetComponent<Collider2D>().bounds.extents.y));
partialExtent = minimumExtent * (1.0f - skinWidth);
sqrMinimumExtent = minimumExtent * minimumExtent;
}
void FixedUpdate()
{
//have we moved more than our minimum extent?
Vector2 movementThisStep = myRigidbody.position - previousPosition;
float movementSqrMagnitude = movementThisStep.sqrMagnitude;
if (movementSqrMagnitude > sqrMinimumExtent)
{
float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);
//RaycastHit2D hitInfo;
//check for obstructions we might have missed
if (Physics2D.Raycast(previousPosition, movementThisStep, movementMagnitude, 0, layerMask.value))
myRigidbody.position = (movementThisStep/movementMagnitude)*partialExtent;
Debug.DrawLine(myRigidbody.position, myRigidbody.position - previousPosition, Color.green);
}
previousPosition = myRigidbody.position;
}
This is unitypackage https://www.dropbox.com/s/a3n1dalbc1k0k42/Hat%20Trick.unitypackage?dl=0
P.S. Sorry for my english and thank you for help!!
Explanation
Continuous collision detection in Unity does not use raycasting. As a result, very fast moving (and/or comparatively small) objects (let's call that kind of object projectile for now) still pass through things without a collision being detected. The famous DontGoThroughThings component fixes that for 3D. There are a few inconsistencies, but it can get the job done if you know what you are doing.
Here is my 2D adaption of it.
I added some features to make it more user-friendly to everyone who is not that good at coding or game physics.
How to use it
Add this component to your fast moving objects and they will always trigger the OnTriggerEnter2D event when hitting something.
You can also chose to send a different, custom message instead (by changing the MessageName variable). I actually recommend that due to the caveat explained below.
Sending messages is the script's primary use case. It will not magically make a projectile behave correctly in a physical sense.
The triggerTarget variable determines whether it sends the message to itself (in case, you have the hit handling script attached to the projectile), to the object being hit (in case, you have the hit handling attached to the objects that should be hit by projectiles), or any variation of the two.
Unlike the original version, this script also allows for force to be applied upon impact which can be tuned through the momentumTransferFraction variable. When two objects collide the force generated is a result of a transfer of momentum (mass times velocity) between the two objects. The way I do this is very rudimentary and it is missing a lot of contributing factors, but it is enough to have projectiles push objects on impact. Just like in the real world, the faster or heavier your projectile is, the more force is exerted.
There are also some caveats (most of which also apply to the original version)
Only apply on this on very fast moving objects. The less you use it the better because it is quite a bit more computationally expensive than the normal collision detection.
While collision detection is more accurate, Collision resolution is only very rudimentary. It is not as good as what the physics engine does by default.
In the current version, collisions are always detected in hindsight. That is why you might see projectiles having gone through the object by the time the collision is registered. I want to fix that in the near future.
If you use this on objects like bullets or other forms of projectiles that basically stop working after first hit, you can set momentumTransferFraction to 1 to let the bullet physically push the object (by applying all its momentum to the first hit object) without the bullet being affected itself.
For some reason, you cannot disable default collision detection just for one object. This means that if you are so (un-)lucky and a collision happens to be registered by Unity's default collision checks, you might have OnTriggerEnter2D fire multiple times on the same object, or (if collider is not a trigger) exert a force on hit targets (in addition to the one exerted by this script). However, since that would be somewhat random and very inconsistent, in addition to turning on IsTrigger on your projectile's collider, I recommend using a custom message name to handle projectile impacts. This way, collisions that are randomly detected by default collision detection would not have any unintended side effects [Remember that default collision detection being inconsistent for these sorts of objects is the actual reason why you add this script]. FYI: As of Unity 5, the only two ways to prevent default collision detection are IgnoreCollision and IgnoreLayerCollision.
Code
using UnityEngine;
using System.Collections;
using System.Linq;
/// <summary>
/// 2D adaption of the famous DontGoThroughThings component (http://wiki.unity3d.com/index.php?title=DontGoThroughThings).
/// Uses raycasting to trigger OnTriggerEnter2D events when hitting something.
/// </summary>
/// <see cref="http://stackoverflow.com/a/29564394/2228771"/>
public class ProjectileCollisionTrigger2D : MonoBehaviour {
public enum TriggerTarget {
None = 0,
Self = 1,
Other = 2,
Both = 3
}
/// <summary>
/// The layers that can be hit by this object.
/// Defaults to "Everything" (-1).
/// </summary>
public LayerMask hitLayers = -1;
/// <summary>
/// The name of the message to be sent on hit.
/// You generally want to change this, especially if you want to let the projectile apply a force (`momentumTransferFraction` greater 0).
/// If you do not change this, the physics engine (when it happens to pick up the collision)
/// will send an extra message, prior to this component being able to. This might cause errors or unexpected behavior.
/// </summary>
public string MessageName = "OnTriggerEnter2D";
/// <summary>
/// Where to send the hit event message to.
/// </summary>
public TriggerTarget triggerTarget = TriggerTarget.Both;
/// <summary>
/// How much of momentum is transfered upon impact.
/// If set to 0, no force is applied.
/// If set to 1, the entire momentum of this object is transfered upon the first collider and this object stops dead.
/// If set to anything in between, this object will lose some velocity and transfer the corresponding momentum onto every collided object.
/// </summary>
public float momentumTransferFraction = 0;
private float minimumExtent;
private float sqrMinimumExtent;
private Vector2 previousPosition;
private Rigidbody2D myRigidbody;
private Collider2D myCollider;
//initialize values
void Awake()
{
myRigidbody = GetComponent<Rigidbody2D>();
myCollider = GetComponents<Collider2D> ().FirstOrDefault();
if (myCollider == null || myRigidbody == null) {
Debug.LogError("ProjectileCollisionTrigger2D is missing Collider2D or Rigidbody2D component", this);
enabled = false;
return;
}
previousPosition = myRigidbody.transform.position;
minimumExtent = Mathf.Min(myCollider.bounds.extents.x, myCollider.bounds.extents.y);
sqrMinimumExtent = minimumExtent * minimumExtent;
}
void FixedUpdate()
{
//have we moved more than our minimum extent?
var origPosition = transform.position;
Vector2 movementThisStep = (Vector2)transform.position - previousPosition;
float movementSqrMagnitude = movementThisStep.sqrMagnitude;
if (movementSqrMagnitude > sqrMinimumExtent) {
float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);
//check for obstructions we might have missed
RaycastHit2D[] hitsInfo = Physics2D.RaycastAll(previousPosition, movementThisStep, movementMagnitude, hitLayers.value);
//Going backward because we want to look at the first collisions first. Because we want to destroy the once that are closer to previous position
for (int i = 0; i < hitsInfo.Length; ++i) {
var hitInfo = hitsInfo[i];
if (hitInfo && hitInfo.collider != myCollider) {
// apply force
if (hitInfo.rigidbody && momentumTransferFraction != 0) {
// When using impulse mode, the force argument is actually the amount of instantaneous momentum transfered.
// Quick physics refresher: F = dp / dt = m * dv / dt
// Note: dt is the amount of time traveled (which is the time of the current frame and is taken care of internally, when using impulse mode)
// For more info, go here: http://forum.unity3d.com/threads/rigidbody2d-forcemode-impulse.213397/
var dv = myRigidbody.velocity;
var m = myRigidbody.mass;
var dp = dv * m;
var impulse = momentumTransferFraction * dp;
hitInfo.rigidbody.AddForceAtPosition(impulse, hitInfo.point, ForceMode2D.Impulse);
if (momentumTransferFraction < 1) {
// also apply force to self (in opposite direction)
var impulse2 = (1-momentumTransferFraction) * dp;
hitInfo.rigidbody.AddForceAtPosition(-impulse2, hitInfo.point, ForceMode2D.Impulse);
}
}
// move this object to point of collision
transform.position = hitInfo.point;
// send hit messages
if (((int)triggerTarget & (int)TriggerTarget.Other) != 0 && hitInfo.collider.isTrigger) {
hitInfo.collider.SendMessage(MessageName, myCollider, SendMessageOptions.DontRequireReceiver);
}
if (((int)triggerTarget & (int)TriggerTarget.Self) != 0) {
SendMessage(MessageName, hitInfo.collider, SendMessageOptions.DontRequireReceiver);
}
}
}
}
previousPosition = transform.position = origPosition;
}
}
Here is the 2D version I rewrote of this script (for Unity 4.6):
using UnityEngine;
using System.Collections;
public class DontGoThroughThings : MonoBehaviour
{
public delegate void CollidedDelegate(Collider2D collider);
public event CollidedDelegate Collided;
public LayerMask layerMask; //make sure we aren't in this layer
public float skinWidth = 0.1f; //probably doesn't need to be changed
private float minimumExtent;
private float partialExtent;
private float sqrMinimumExtent;
private Vector2 previousPosition;
private Rigidbody2D myRigidbody;
//initialize values
void Awake()
{
myRigidbody = rigidbody2D;
previousPosition = myRigidbody.transform.position;
minimumExtent = Mathf.Min(BoundsOf(collider2D).extents.x, BoundsOf(collider2D).extents.y);
partialExtent = minimumExtent * (1.0f - skinWidth);
sqrMinimumExtent = minimumExtent * minimumExtent;
}
void FixedUpdate()
{
//have we moved more than our minimum extent?
Vector2 movementThisStep = (Vector2)myRigidbody.transform.position - previousPosition;
float movementSqrMagnitude = movementThisStep.sqrMagnitude;
if (movementSqrMagnitude > sqrMinimumExtent)
{
float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);
//check for obstructions we might have missed
RaycastHit2D[] hitsInfo = Physics2D.RaycastAll(previousPosition, movementThisStep, movementMagnitude, layerMask.value);
//Going backward because we want to look at the first collisions first. Because we want to destroy the once that are closer to previous position
for (int i = hitsInfo.Length-1; i >= 0; i--)
{
var hitInfo = hitsInfo[i];
if (hitInfo && hitInfo.rigidbody != rigidbody2D)
{
if (Collided != null)
{
Collided(hitInfo.collider);
}
}
}
}
previousPosition = myRigidbody.transform.position;
}
// compute bounds in local space
public static Bounds BoundsOf(Collider2D collider) {
var bounds = new Bounds();
var bc = collider as BoxCollider2D;
if (bc) {
var ext = bc.size * 0.5f;
bounds.Encapsulate(new Vector3(-ext.x, -ext.y, 0f));
bounds.Encapsulate(new Vector3(ext.x, ext.y, 0f));
return bounds;
}
var cc = collider as CircleCollider2D;
if (cc) {
var r = cc.radius;
bounds.Encapsulate(new Vector3(-r, -r, 0f));
bounds.Encapsulate(new Vector3(r, r, 0f));
return bounds;
}
// others :P
//Debug.LogWarning("Unknown type "+bounds);
return bounds;
}
// return bounds in world space
public static Bounds BoundsColliders(GameObject obj) {
var bounds = new Bounds(obj.transform.position, Vector3.zero);
var colliders = obj.GetComponentsInChildren<Collider2D>();
foreach(var c in colliders) {
var blocal = BoundsOf(c);
var t = c.transform;
var max = t.TransformPoint(blocal.max);
bounds.Encapsulate(max);
var min = t.TransformPoint(blocal.min);
bounds.Encapsulate(min);
}
return bounds;
}
}
Please let me know if it works for you.
Thanks,
Lidan

Having FPS lags when drawing tiles in XNA

I am developing my own tile-based game in xna 4.0, and i suffer big fps lags while drawing the tiles on the screen.
I've read a lot about increasing performance and i've got to this:
I store my tiles in a simple dictionary
private Dictionary<Vector2, IBlock> WorldBlocks;
private Vector2 ExactBlockPosition;
private IBlock ExistingBlock;
public void Draw(SpriteBatch SpriteBatch, Vector2 ScreenStart, Vector2 ScreenEnd)
{
// Run over all the blocks in the screen
for (this.ExactBlockPosition.X = this.GetCurrentBlockXPosition(ScreenStart.X);
this.ExactBlockPosition.X < ScreenEnd.X;
this.ExactBlockPosition.X += Global.BLOCK_WIDTH)
{
for (this.ExactBlockPosition.Y = this.GetCurrentBlockYPosition(ScreenStart.Y);
this.ExactBlockPosition.Y < ScreenEnd.Y;
this.ExactBlockPosition.Y += Global.BLOCK_HEIGHT)
{
// Check if there is a block in the exact block location
if (this.WorldBlocks.TryGetValue(this.ExactBlockPosition, out this.ExistingBlock))
{
// Draw the block on the screen
this.ExistingBlock.Draw(SpriteBatch);
}
}
}
}
private int GetCurrentBlockXPosition(float X)
{
return (int)(X - X % Global.BLOCK_WIDTH);
}
private int GetCurrentBlockYPosition(float Y)
{
return (int)(Y - Y % Global.BLOCK_WIDTH);
}
In short, this code is drawing the blocks that are on the screen only.
But still my fps falls to 31 when there is a lot of tiles on the screen.
The tile width and heigh is 20 pixels.
Any suggestions why my fps falls?

Java - drawing many images with Graphics.drawImage() and 2-screen buffer strategy distorts and cuts images

I am using a loop to invoke double buffering painting. This, together with overriding my only Panel's repaint method, is designed to pass complete control of repaint to my loop and only render when it necessary (i.e. some change was made in the GUI).
This is my rendering routine:
Log.write("renderer painting");
setNeedsRendering(false);
Graphics g = frame.getBufferStrategy().getDrawGraphics();
g.setFont(font);
g.setColor(Color.BLACK);
g.fillRect(0, 0, window.getWidth(),window.getHeight());
if(frame != null)
window.paint(g);
g.dispose();
frame.getBufferStrategy().show();
As you can see, it is pretty standard. I get the grpahics object from the buffer strategy (initialized to 2), make it all black and pass it to the paint method of my "window" object.
After window is done using the graphics object, I dispose of it and invoke show on the buffer strategy to display the contents of the virtual buffer.
It is important to note that window passes the graphics object to many other children components the populate the window and each one, in turn, uses the same instance of the graphics object to draw something onto the screen: text, shapes, or images.
My problem begins to show when the system is running and a large image is rendered. The image appears to be cut into seveeal pieces and drawn again and again (3-4 times) with different offsets inside of where the image is supposed to be rendered. See my attached images:
This is the original image:
alt text http://img109.imageshack.us/img109/8308/controller.png
This is what I get:
alt text http://img258.imageshack.us/img258/3248/probv.png
Note that in the second picture, I am rendering shapes over the picture - these are always at the correct position.
Any idea why this is happening?
If I save the image to file, as it is in memory, right before the call to g.drawImage(...) it is identical to the original.
Uh, you are using Swing ?
Normally Swing automatically renders the image, you can't switch it off. The repaint()
method is out of bounds because Swing has a very complicated rendering routine due to
method compatibility for AWT widgets and several optimizations, inclusive drawing only
when necessary !
If you want to use the High-Speed Drawing API, you use a component with a BufferStrategy
like JFrame and Window, use
setIgnoreRepaint(false);
to switch off Swing rendering, set up a drawing loop and paint the content itself.
Or you can use JOGL for OpenGL rendering. The method you are using seems completely
at odds with correct Java2D usage.
Here the correct use:
public final class FastDraw extends JFrame {
private static final transient double NANO = 1.0e-9;
private BufferStrategy bs;
private BufferedImage frontImg;
private BufferedImage backImg;
private int PIC_WIDTH,
PIC_HEIGHT;
private Timer timer;
public FastDraw() {
timer = new Timer(true);
JMenu menu = new JMenu("Dummy");
menu.add(new JMenuItem("Display me !"));
menu.add(new JMenuItem("Display me, too !"));
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
setJMenuBar(menuBar);
setIgnoreRepaint(true);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
super.windowClosing(evt);
timer.cancel();
dispose();
System.exit(0);
}
});
try {
backImg = javax.imageio.ImageIO.read(new File("MyView"));
frontImg = javax.imageio.ImageIO.read(new File("MyView"));
}
catch (IOException e) {
System.out.println(e.getMessage());
}
PIC_WIDTH = backImg.getWidth();
PIC_HEIGHT = backImg.getHeight();
setSize(PIC_WIDTH, PIC_HEIGHT);
createBufferStrategy(1); // Double buffering
bs = getBufferStrategy();
timer.schedule(new Drawer(),0,20);
}
public static void main(String[] args) {
new FastDraw();
}
private class Drawer extends TimerTask {
private VolatileImage img;
private int count = 0;
private double time = 0;
public void run() {
long begin = System.nanoTime();
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
GraphicsConfiguration gc = g.getDeviceConfiguration();
if (img == null)
img = gc.createCompatibleVolatileImage(PIC_WIDTH, PIC_HEIGHT);
Graphics2D g2 = img.createGraphics();
// Zeichenschleife
do {
int valStatus = img.validate(gc);
if (valStatus == VolatileImage.IMAGE_OK)
g2.drawImage(backImg,0,0,null);
else {
g.drawImage(frontImg, 0, 0, null);
}
// volatile image is ready
g.drawImage(img,0,50,null);
bs.show();
} while (img.contentsLost());
time = NANO*(System.nanoTime()-begin);
count++;
if (count % 100 == 0)
System.out.println(1.0/time);
}
}

Resources